【问题标题】:Best way to draw scrollmap绘制滚动图的最佳方法
【发布时间】:2013-10-09 17:39:12
【问题描述】:

我想在canvas 上绘制一个scrollmap,它有一堆Y 坐标。

这样做最有效的是什么?我想带有一些平均点的渐变是最好的方法,但我不知道该怎么做。

我现在想做的是用red 填充画布,然后从顶部到每个Y 坐标绘制green 矩形。如果矩形具有一定程度的透明度,则应该会产生相当不错的滚动热图。

还有其他想法吗?或者如果有人知道如何实现渐变,那就太好了。

如果您不知道,滚动图应该如下所示:

【问题讨论】:

  • 为什么要为此使用画布,而不是常规的 100% 高度/宽度 div,具有 css3 渐变背景 (colorzilla.com/gradient-editor/…) 和不透明度:0.3 之类的?
  • 好吧,canvas 方法不是更容易编码然后使用 javaScript 生成跨设备CSS3 渐变吗?通过使用 CSS 渐变,我必须为所有浏览器替换所有停止点的位置。我知道渐变或具有超过 2 个停止点的 IE 确实有问题,特别是如果其中一些点重合。不过好点,我也会试试的。 (我要画布是因为我已经使用了带有 heatmap.js 的画布,所以 canvas 已经存在了,我只需要在上面画一个渐变...
  • 另外真正的问题是not如何绘制渐变,但是如何通过拥有许多Y高度来找到渐变的停止点。
  • 这取决于您要定位的目标。您是否有“它应该在......中工作”和“理想情况下也在......”的列表?例如,css3 渐变在所有当前 gen 桌面浏览器中都很容易(ie10/11 会很乐意做多站渐变)。如果您已经有了画布,那么首先要找到 RGB 原色 + 副色的停靠点,然后进行简单的插值(在两个简单的 lerps 中执行 255/0/0 到 255/255/0 到 0/255/0 而不是复杂的颜色插值让生活变得轻松)
  • 是的,我知道,但是找到这些停止点的最相关和最简单的方法是什么?我正在考虑对点进行升序排序,然后如果我需要 5 个停靠点,则获取在此排序数组中的以下位置找到的 5 个元素的 Y 值:0、1*NrY/5、2*NrY/5 等。但是,如果假设所有 Y 都相同,这不会生成准确的热图。

标签: javascript html canvas linear-gradients processing.js


【解决方案1】:

根据来自 cmets 的其他信息,您可能希望使用分箱方法。如果我们将页面分割成 X 个高度区域(每个区域的高度为 1/X 倍 pageheight),那么我们可以简单地根据哪个“bin”执行计数用户的最终滚动高度落入。在 JSesque 伪代码中:

var X = 5, bins = [], idx;
userScrollHeights.forEach(function(Y) {
  idx = Math.floor(map(Y, 0, pageHeight, 0, X));
  bins[id] = bins[idx] ? bins[idx]++ : 1;
});

奇怪的是,标准 JS API 中缺少映射功能,但很容易实现为:

function map(value, istart, istop, ostart, ostop) {
  return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));
}

bins 数组现在包含每个 bin 的“强度”。您选择的 bin 越多,您的滚动图就越准确。

当然,基本的滚动图不是彩色的,它只是强度,所以它更自然地是白到黑的叠加。如果您真的想要一张彩色地图,“最强烈”映射到红色,“最不强烈”映射到紫色,您可以使用具有 255 个 bin 的设置,并在找到最大值后简单地将每个强度级别映射到颜色值强度:

var bin_max = 0;
bins.forEach(function(value) {
  if(value > bin_max) bin_max= value;
});

随后是基于“彩虹”渐变中的五个切片的颜色映射:

function mapIntensityToColor(intensity, min, max) {
  var cint = map(intensity,min,max,0,255);
  var step = (max - min) / 5;
  if(cint > 204) 
    return [255, map(intensity, max-step,max, 255,0), 0];
  if(cint > 153) 
    return [map(intensity, max-2*step,max-step, 0,255), 255, 0];
  if(cint > 102) 
    return [0, 255, map(intensity, max-3*step,max-2*step, 255,0)];
  if(cint > 51)
    return [0, map(intensity, max-4*step,max-3*step, 0,255), 255];
  return [map(intensity, min,max-4*step, 255,0), 0, 255];
}

将您的画布(或 div)分割为 255 个步骤,并根据 mapIntensityToColor(bin[step_number], 0, bin_max) 为每个步骤着色,现在应该可以为您提供准确的滚动图。

【讨论】:

  • 我在 javascript 中实现了你的 sudo 代码,mapIntensityToColor 函数给了我像 [-1020.0000000000002, 0, 255] 这样的值。可以看到 red 的值为负数,不在 0 到 255 之间,如何解决?
  • 这不是伪代码,这已经是 Javascript,您不必更改单个字母即可使其工作。 mapIntensityToColor 函数使用了什么输入?
  • 如果 bin 数组 [11, 7, 0, 0,.....,0] 和 bin_max = 11,那么第一个 mapIntensityToColor 函数应该像 mapIntensityToColor(11, 0, 11) 一样调用并给出输出 @ 987654331@
  • 啊,看起来代码忘记重新映射初始的intensity。解决了这个问题。
  • 你能告诉我更多关于这个map函数的信息吗?我只是好奇这个函数背后的逻辑是什么,以及它与mapIntensityToColor 函数的关系如何。我想知道你有什么想法或方法来解决这个问题。
猜你喜欢
  • 1970-01-01
  • 2011-11-13
  • 2013-06-01
  • 2013-01-29
  • 1970-01-01
  • 1970-01-01
  • 2014-09-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多