放大 Plotly 热图

2023-11-29

目前 Plotly.JS 热图中有 2 种“缩放”行为:

  1. 在这里,您可以采用任何矩形形状进行缩放(单击、拖放)。但是像素不是正方形的,这对于某些应用程序来说是不行的(不保留长宽比,有时应该保留):

        const z = Array.from({length: 500}, () => Array.from({length: 100}, () => Math.floor(Math.random() * 255)));
        Plotly.newPlot('plot', [{type: 'heatmap', z: z}], {});
        <script src="https://cdn.plot.ly/plotly-2.16.2.min.js"></script>
        <div id="plot"></div>
  2. 这里是像素是正方形的谢谢{'yaxis': {'scaleanchor': 'x'}}, 但是之后您只能缩放具有特定纵横比的矩形形状,这有时是 UX/UI 的限制因素:

        const z = Array.from({length: 500}, () => Array.from({length: 100}, () => Math.floor(Math.random() * 255)));
        Plotly.newPlot('plot', [{type: 'heatmap', z: z}], {'yaxis': {'scaleanchor': 'x'}});
        <script src="https://cdn.plot.ly/plotly-2.16.2.min.js"></script>
        <div id="plot"></div>

Question:如何同时拥有两者,即可以绘制任意形状的矩形选择缩放?并保留正方形像素?缩放的对象应位于绘图的中心(如果需要,可以使用水平或垂直空白)。


一种方法是首先设置scaleanchor与期望的约束scaleratio,这样一旦绘制了图形,我们就可以计算约束缩放范围比,从而产生所需的像素与单位比例,而无需太多麻烦。

然后,我们可以删除约束并附加一个情节重排事件处理程序将在必要时进行调整。由于这些调整是通过调用精确地进行的Plotly.relayout(),我们通过条件块并通过仅考虑合理数量的有效数字来比较范围比来防止无限循环。

如果重新布局后的比率与目标(受限)比率不匹配,我们将通过扩大其中一个轴范围(而不是缩小另一个轴范围)来调整它,同时保持用户创建的缩放窗口相对于调整范围居中。

const z = Array.from({length: 500}, () => Array.from({length: 100}, () => Math.floor(Math.random() * 255)));

const data = [{
  type: 'heatmap',
  z: z
}];

const layout = {
  xaxis: {
    constrain: 'range',
    constraintoward: 'center',
    scaleanchor: "y",
    scaleratio: 1
  }
};

Plotly.newPlot('plot', data, layout).then(afterPlot);

function afterPlot(gd) {
  // Reference each axis range
  const xrange = gd._fullLayout.xaxis.range;
  const yrange = gd._fullLayout.yaxis.range;

  // Needed when resetting scale
  const xrange_init = [...xrange];
  const yrange_init = [...yrange];

  // Compute the actual zoom range ratio that produces the desired pixel to unit scaleratio
  const zw0 = Math.abs(xrange[1] - xrange[0]);
  const zh0 = Math.abs(yrange[1] - yrange[0]);
  const r0 = Number((zw0 / zh0).toPrecision(6));

  // Now we can remove the scaleanchor constraint
  // Nb. the update object references gd._fullLayout.<x|y>axis.range
  const update = {
    'xaxis.range': xrange,
    'yaxis.range': yrange,
    'xaxis.scaleanchor': false,
    'yaxis.scaleanchor': false
  };

  Plotly.relayout(gd, update);

  // Attach the handler that will do the adjustments after relayout if needed
  gd.on('plotly_relayout', relayoutHandler);

  function relayoutHandler(e) {
    if (e.width || e.height) {
      // The layout aspect ratio probably changed, need to reapply the initial
      // scaleanchor constraint and reset variables
      return unbindAndReset(gd, relayoutHandler);
    }

    if (e['xaxis.autorange'] || e['yaxis.autorange']) {
      // Reset zoom range (dblclick or "autoscale" btn click)
      [xrange[0], xrange[1]] = xrange_init;
      [yrange[0], yrange[1]] = yrange_init;
      return Plotly.relayout(gd, update);
    }

    // Compute zoom range ratio after relayout
    const zw1 = Math.abs(xrange[1] - xrange[0]);
    const zh1 = Math.abs(yrange[1] - yrange[0]);
    const r1 = Number((zw1 / zh1).toPrecision(6));

    if (r1 === r0) {
      return; // nothing to do
    }

    // ratios don't match, expand one of the axis range as necessary

    const [xmin, xmax] = getExtremes(gd, 0, 'x');
    const [ymin, ymax] = getExtremes(gd, 0, 'y');

    if (r1 > r0) {
      const extra = (zh1 * r1/r0 - zh1) / 2;
      expandAxisRange(yrange, extra, ymin, ymax);
    }
    if (r1 < r0) {
      const extra = (zw1 * r0/r1 - zw1) / 2;
      expandAxisRange(xrange, extra, xmin, xmax);
    }

    Plotly.relayout(gd, update);
  }
}

function unbindAndReset(gd, handler) {
  gd.removeListener('plotly_relayout', handler);

  // Careful here if you want to reuse the original `layout` (eg. could be
  // that you set specific ranges initially) because it has been passed by
  // reference to newPlot() and been modified since then.
  const _layout = {
    xaxis: {scaleanchor: 'y', scaleratio: 1, autorange: true},
    yaxis: {autorange: true}
  };

  return Plotly.relayout(gd, _layout).then(afterPlot);
}

function getExtremes(gd, traceIndex, axisId) {
  const extremes = gd._fullData[traceIndex]._extremes[axisId];
  return [extremes.min[0].val, extremes.max[0].val];
}

function expandAxisRange(range, extra, min, max) {
  const reversed = range[0] > range[1];
  if (reversed) {
    [range[0], range[1]] = [range[1], range[0]];
  }
  
  let shift = 0;
  if (range[0] - extra < min) {
    const out = min - (range[0] - extra);
    const room = max - (range[1] + extra);
    shift = out <= room ? out : (out + room) / 2;
  }
  else if (range[1] + extra > max) {
    const out = range[1] + extra - max;
    const room = range[0] - extra - min;
    shift = out <= room ? -out : -(out + room) / 2;
  }

  range[0] = range[0] - extra + shift;
  range[1] = range[1] + extra + shift;

  if (reversed) {
    [range[0], range[1]] = [range[1], range[0]];
  }
}
<script src="https://cdn.plot.ly/plotly-2.22.0.min.js"></script>
<div id="plot"></div>

铌。在处理程序中,除了检查用户是否刚刚重置比例时之外,我们使用对gd._fullLayout.<x|y>axis.range而不是检查包含的内容e(传入的事件对象),因为引用始终是最新的,并且它们的结构永远不会改变,这与仅反映更新内容的事件参数不同。另外,因为update对象本身引用这些引用,它允许稍微不那么冗长,只需调用Plotly.relayout(gd, update)修改范围后。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

放大 Plotly 热图 的相关文章

  • 在 Three.js 中绕点旋转对象的正确方法是什么?

    关于 Three js 的大多数教程 问题都建议使用 Three js 绕点旋转对象的方法是在要旋转的位置创建父对象 附加对象 然后移动子对象 然后 当父级旋转时 子级围绕该点旋转 例如 Make a pivot var pivot new
  • jQuery mobile 中的文本区域高度和宽度?

    我修复了 jQuery mobile 中文本区域元素的高度 并且在纵向中得到了完美的高度和宽度 但在横向中宽度没有放大 谁能帮我 提前致谢 HTML
  • 将 Javascript 对象的属性从 string 更改为 int

    我有一个对象数组 每个对象具有三个属性 年份 总计 人均 例子 0 Object per capita 125 8 total 1007 2 year 2009 这些属性是字符串 我想创建一个循环来遍历数组并将它们转换为 int 我尝试了以
  • 如何阻止直接访问我的 JavaScript 文件?

    我使用 Minify 来缩小并缓存所有脚本请求 我只希望我的用户能够访问 JavaScript 文件的缩小版本 缩小位于www example com min我的脚本位于www example com scripts 如何阻止直接访问doc
  • 浏览器视口大小(以设备像素为单位)

    Goal 我希望 Flash 能够获得有关浏览器视口宽度和高度 以设备像素为单位 的准确信息初始化 调整大小或浏览器缩放事件时 规格 我需要将 flash 嵌入到在 chrome safari firefox 等中运行的 html 页面中
  • Firebase,只得到新的孩子[重复]

    这个问题在这里已经有答案了 var firebase new Firebase firebaseRef on child added function snapshot 这将接收所有元素 有没有办法在创建新的 Firebase 引用时不接收
  • 在 Internet Explorer 中使用什么来监视 jscript 内存使用情况

    我们正在调试 GWT 应用程序 在 Firefox 中运行正常 在 IE6 0 中开始运行正常 但一段时间后 它就会崩溃并开始爬行 经过一些测试后 我们怀疑存在一些内存问题 使用了太多内存 内存泄漏等 除了使用taskmanager和pro
  • 从函数返回函数的目的是什么?

    阅读一些遗留代码 发现 A prototype setSize function var v1 new Vector2 return function size var halfSize v1 copy size multiplyScala
  • Vue 3 Composition API 提供/注入在单文件组件中不起作用

    我正在使用 Composition API 在 VueJS 3 中创建一个库 我实现了提供 注入 如中所述docs https v3 vuejs org guide composition api provide inject html i
  • 如何在网站上使用 svg 元素制作块的屏幕截图?

    我在网站上创建了一个构造函数 其本质是将所选元素及其颜色 svg中的元素 添加到访问者选择的背景和背景颜色 png中的背景 中 然后必须单击 保存 结果 按钮并仅执行工作区的屏幕截图 我写了这个脚本 但它需要屏幕截图 但只有背景 并忽略选定
  • 如何使用 Javascript 设置查询字符串

    有没有办法使用 javascript 设置查询字符串的值 我的页面有一个过滤器列表 单击该列表时 它将更改右侧的页内结果窗格 我正在尝试更新 url 的查询字符串值 因此如果用户离开页面 然后单击 后退 按钮 他们将返回到最后一个过滤器选择
  • 将 Firebase 云消息传递与 Windows 应用程序结合使用

    我在 Android 和 iOS 应用程序中使用 Firebase Cloud Messaging 但是我还有此应用程序的 Windows Mac OS 版本 我想保留相同的逻辑 我知道 Firebase Cloud Messaging 可
  • 如何在另一个自定义 Hook 中使用返回值的自定义 Hook?

    我正在使用 React native 其中有一个名为的自定义 HookuseUser使用以下方法从 AWS Amplify 获取用户信息Auth getUserInfro方法 然后获取返回对象的一部分并用它设置一个状态变量 我还有另一个名为
  • Vaadin 12 将对象传递给 JavaScript 函数:无法对类进行编码

    Vaadin 12 Kotlin 项目 In my myPage html我有JavaScript myObject redirectToCheckout sessionId 1111 2222 所以我需要调用javaScript函数red
  • 聆听 Angular 2 中的元素可见性

    我正在为我的网络应用程序使用 Bootstrap 和 Angular 2 v4 我想监听指令中的元素以了解可见性变化 我的元素有一个可以隐藏其子元素的父元素hidden sm up我需要在每次隐藏或显示时触发一个函数 div hidden
  • Google Maps API (v3) 添加/更新标记

    编辑 它现在可以工作 但如果用户不允许或没有基于位置的服务 则不会加载 请参阅 jsfiddle 示例接受的答案评论 我已经浏览了一些教程和问题 但我无法安静地理解正在发生的事情 或者在这种情况下 没有发生 当用户单击链接时 我正在加载地图
  • 主页(网格)上的缩略图现在显得模糊。如何纠正?

    我不知道这看起来是否愚蠢 但从早上开始我就无法纠正这个突然出现在我的博客网站上的错误www candidopinions in http www candidopinions in 我有一个网格视图模板 其中博客文章中的特色图像作为调整大小
  • 使用 Enzyme 测试 `React.createRef` api

    我想测试下面的类 它使用React createRef api 不过 快速搜索并没有发现任何这样做的例子 有人成功过吗 我该如何嘲笑裁判 理想情况下我想使用shallow class Main extends React Component
  • 测量窗口偏移

    有没有一种方法可以测量 jQuery 中窗口的偏移量 以便我可以比较 固定 元素和相对定位元素的位置 我需要能够知道窗口滚动了多远 以便我可以使用该图来计算固定元素的高度 相对于视口顶部 和相对对象的高度 相对于顶部 之间的差异文件的内容
  • 使用velocity.js制作可拖动元素的动画

    我正在使用velocity js 为用户拖动的可拖动 SVG 元素设置动画 然而 velocity js 将先前的 mousemove 坐标排队并通过所有后续的 mousemove 坐标进行动画处理 我想要的是velocity js 不要对

随机推荐

  • 为什么 .length 不是一个需要 () 的方法

    JavaScript中为什么关键字长度不需要 似乎所有其他函数 例如 splice shift 都需要括号 我们只能推测为什么它被设为普通属性而不是方法 但是 那 length是每个字符串 数组的常量值 它在计算时不会修改任何内容 它不像方
  • 避免警告“非依赖属性的设置方法不应访问...”

    我有一个类 它有一些属性 并且有 2 个相关 在示例中称为param1 param2 他们是独立的 只是受到约束 param2必须一样大或大于param1并且必须始终存在 如果param1做 有问题的代码类似于 function set p
  • boost asio 缓冲区延迟分配

    异步操作 现在我传递预分配的字节缓冲区 例如 s async receive from boost asio buffer preallocated pointer preallocated size remote endpoint boo
  • 如何从一个 HTML5 画布拖放到另一个画布

    我试图弄清楚如何将图像从一个画布拖放到另一个画布 假设画布彼此相邻 是否可以无缝地将某些东西拖过边界 如果不是 将 div 拖到画布上 获取其 ID 然后通过响应画布上的 mouseup 位置来放置它是不是更好 您不能在画布上拖动项目 画布
  • 如何检查是否有任何 JavaScript 事件侦听器/处理程序附加到元素/文档? [复制]

    这个问题在这里已经有答案了 尝试在线搜索 但看起来我无法正确制定搜索查询 我如何使用 jQuery 或仅使用 javascript 列出附加到元素 文档 窗口或存在于 DOM 中的所有处理程序或事件侦听器 在 1 8 之前的 jQuery
  • 有理数 - ruby​​ 中的原始数字

    如何获得原始号码 例如当我输入 r Rational 2 10 1 5 2和10将更改为1和5 r numerator 1 r denominator 5 如何从 Rational 类的实例中获取 2 和 10 r 我对 Rational
  • Android:DCIM 文件夹中的重复照片存储

    我正在使用本机 Android 相机并将文件保存到应用程序数据文件夹 mnt sdcard Pictures 同时 在某些设备上 照片的另一个副本会保存到 DCIM 文件夹中 这是我的代码 private void startStockCa
  • Inno Setup 根据可执行调用的结果有条件重新启动

    我的 Inno Setup 脚本用于安装驱动程序 它运行我的InstallDriver exe在步骤中复制此文件后ssInstall 我需要根据返回的值要求用户在某些情况下重新启动InstallDriver exe 这意味着我不能把Inst
  • Pandas dataframe:从列中的字符串中提取浮点值

    我正在尝试从特定列的字符串中提取浮动值 原始输出 DATE strCondition 4 3 2018 2 9 4 3 2018 3 1 text 4 3 2018 2 6 text 4 3 2018 text 2 7 和其他变化 我也尝试
  • ASP.NET MVC 下的 SSL 页面

    如何对基于 ASP NET MVC 的站点中的某些页面使用 HTTPS Steve Sanderson 在预览版 4 上有一个关于如何以 DRY 方式执行此操作的非常好的教程 网址为 http blog codeville net 2008
  • Django,使用其他表中的数据进行注释和排序

    在我的应用程序中 有请求物品的用户和捐赠这些物品的用户 我想获取所有捐款最多的用户 这些是我的模型 class ItemRequest models Model item type models ForeignKey ItemType de
  • 当 html 表单允许文件上传时,Django 停止并显示“生成器引发 StopIteration”

    我的设置是 Windows 10 Python 3 7 Apache 2 4 mod wsgi 当我添加这个时enctype multipart form data 在我的表单中 仅通过添加此属性 仅 没有文件附加到表单 提交时出现此错误
  • nginx。被 CORS 政策阻止

    当前 nginx 配置 server listen hidden 80 server name dev hidden com root var www back hidden api location add header Access C
  • csv 读取引发“UnicodeDecodeError:'charmap'编解码器无法解码...”

    我已经阅读了我能找到的所有帖子 但我的情况似乎很独特 我对 Python 完全陌生 所以这可能是基础的 我收到以下错误 UnicodeDecodeError charmap 编解码器无法解码位置 70 中的字节 0x8d 字符映射到未定义
  • 如何将日期选择器包装在新的 div 中?

    我需要将我的日期选择器放在一个新的 div 中 这将是一个 shadow border div 我尝试过以下方法 beforeShow function input input datepicker widget find ui datep
  • 最大字符串数组 VisualBasic WSH

    我正在 VB 中编写一个 WSH 脚本 以读取通过 Run 方法使用重定向目录列表生成的大量目录列表 目录列表大约有 8400 行 但是每次我运行脚本时 都会出现以下循环 执行直到 DirList AtEndOfStream Redim 保
  • 我可以手动注册/安装 Search.Collat​​orDSO.1

    我目前正在尝试使用 windows search 服务搜索一些索引文件 我的问题是 Windows 搜索无法安装在网络服务器上 因为它是 网络版本 收到的错误消息是 Search Collat orDSO 1 提供程序未在本地计算机上注册
  • Windows 忽略 JAVA_HOME:如何将 JDK 设置为默认值?

    如何说服 Windows 使用 JDK 而不是 JRE 这个问题之前已经在这里和其他地方被问过 如何设置默认 Java 安装 运行时 Windows 问题是 Windows 忽略了JAVA HOME它还忽略了我将 JDK bin 目录作为路
  • 如何检测Android是否完全支持USB?

    我的应用程序使用UsbManager与 USB 摄像头通信 有些设备不支持 USB 这些将返回null for UsbManager context getSystemService Context USB SERVICE 或者他们会抛出一
  • 放大 Plotly 热图

    目前 Plotly JS 热图中有 2 种 缩放 行为 在这里 您可以采用任何矩形形状进行缩放 单击 拖放 但是像素不是正方形的 这对于某些应用程序来说是不行的 不保留长宽比 有时应该保留 const z Array from length