arcgis js 4 使用d3.js 添加滤镜光

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了arcgis js 4 使用d3.js 添加滤镜光相关的知识,希望对你有一定的参考价值。

参考技术A 我们利用d3滤镜为d3元素增加光的效果

我们存一些全局变量

this.animateOption = null;

this.defs = null;

this.animateId = "";

this.feDropShadow = null;

滤镜初始化

function create(option)

this.animateOption = option;

this.defs = this.svg.append("defs");

let linearGradient = this.defs.append("filter")

.attr("id",this.animateOption.id)

.attr("x","-50%")

.attr("y","-50%")

.attr("width","200%")

.attr("height","200%")

this.feDropShadow = linearGradient.append("feDropShadow")

.attr("dx", "0")

.attr("dy","0")

.attr("stdDeviation","0")

.attr("flood-color",this.animateOption.floodColor)



启动滤镜

```javascript

function start()

let multiplier = this.animateOption.speed;

let xDiff= 0.01;

let yDiff= 0.01;

let that = this;

function setBlur(x,y)

that.feDropShadow.attr("stdDeviation",x);



let flag = true;

(function updateMotionBlur()

 更多参考 https://xiaozhuanlan.com/topic/8193652740

将滤色器添加到图像的暗部分,将另一个滤色器添加到图像的亮部分?

【中文标题】将滤色器添加到图像的暗部分,将另一个滤色器添加到图像的亮部分?【英文标题】:Add color filter to dark part of image and another filter to light part of the image? 【发布时间】:2021-11-10 16:23:57 【问题描述】:

我的挑战是在图像的暗部添加滤色器,在图像的亮部添加另一个滤色器。要达到这样的效果https://imgur.com/a/cGmJbs9

我正在使用具有 globalCompositeOperation 效果的画布,但我只能应用一个过滤器而不影响另一个过滤器。

ctx.drawImage(image, 0, 0, 380, 540);
ctx.globalCompositeOperation = 'darken';
ctx.fillStyle = overlayFillColor;
ctx.fillRect(0, 0, 380, 540);

这非常适合根据 globalCompositeOperation 将颜色过滤器应用于黑暗或明亮区域,但如果我添加另一个过滤器,它也会改变前一个过滤器的颜色。

有什么想法吗?

谢谢艾尔斯

【问题讨论】:

【参考方案1】:

有一个不错的 SVG 滤镜组件可以将亮度映射到 alpha:<feColorMatrix type="luminanceToAlpha"/> 由于我们可以在画布中使用 SVG 滤镜,因此我们可以将暗区与亮区分开,并使用合成而不是混合。

这样,您的输入颜色就会被保留。

(async () => 
  const canvas = document.querySelector("canvas");
  const ctx = canvas.getContext("2d");
  const img = new Image();
  img.src = "https://picsum.photos/500/500";
  await img.decode();
  canvas.width = img.width;
  canvas.height = img.height;
  // first we create our alpha layer
  ctx.filter = "url(#lumToAlpha)";
  ctx.drawImage(img, 0, 0);
  ctx.filter = "none";
  const alpha = await createImageBitmap(canvas);
  
  // draw on "light" zone
  ctx.globalCompositeOperation = "source-in";
  ctx.fillStyle = "red";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  // save into an ImageBitmap
  // (note that we could also use a second canvas to do this all synchronously)
  const light = await createImageBitmap(canvas);
  
  // clean canvas
  ctx.globalCompositeOperation = "source-over";
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  // draw on "dark" zone
  ctx.drawImage(alpha, 0, 0);
  ctx.globalCompositeOperation = "source-out";
  ctx.fillStyle = "blue";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  // reintroduce "light" zone
  ctx.globalCompositeOperation = "source-over";
  ctx.drawImage(light, 0, 0);
)().catch(console.error);
<svg   style="visibility:hidden;position:absolute">
  <filter id="lumToAlpha">
    <feColorMatrix type="luminanceToAlpha" />
  </filter>
</svg>
<canvas></canvas>
<!--
  If you don't like having an element in the DOM just for that
  you could also directly set the context's filter to a data:// URI
  url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cfilter%20id%3D%22f%22%3E%3CfeColorMatrix%20type%3D%22luminanceToAlpha%22%2F%3E%3C%2Ffilter%3E%3C%2Fsvg%3E#f");
  but you'd have to wait a least a task (setTimeout(fn, 0))
  because setting filters this way is async...
  Hopefully CanvasFilters will solve this soon enough
-->

请注意,希望我们能在不久的将来拥有 CanvasFilters 对象,这将使 SVG 过滤器更易于使用,并且可以在 Workers 中访问(它们目前还不是......)。 所以对于未来的(或者在 Canary 上打开网络功能标志的现在),这看起来像:

// typeof CanvasFilter === "function"
// should be enough for detecting colorMatrix
// but see below for how to "correctly" feature-detect
// a particular CanvasFilter
if (supportsColorMatrixCanvasFilter()) 
(async () => 
  const canvas = document.querySelector("canvas");
  const ctx = canvas.getContext("2d");
  const img = new Image();
  img.src = "https://picsum.photos/500/500";
  await img.decode();
  canvas.width = img.width;
  canvas.height = img.height;
  // first we create our alpha layer
  ctx.filter = new CanvasFilter(
    filter: "colorMatrix",
    type: "luminanceToAlpha"
  );
  ctx.drawImage(img, 0, 0);
  ctx.filter = "none";
  const alpha = await createImageBitmap(canvas);
  
  // draw on "light" zone
  ctx.globalCompositeOperation = "source-in";
  ctx.fillStyle = "red";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  // save into an ImageBitmap
  // (note that we could also use a second canvas to do this all synchronously)
  const light = await createImageBitmap(canvas);
  
  // clean canvas
  ctx.globalCompositeOperation = "source-over";
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  // draw on "dark" zone
  ctx.drawImage(alpha, 0, 0);
  ctx.globalCompositeOperation = "source-out";
  ctx.fillStyle = "blue";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  // reintroduce "light" zone
  ctx.globalCompositeOperation = "source-over";
  ctx.drawImage(light, 0, 0);
)().catch(console.error);

else 
  console.error("your browser doesn't support CanvasFilters yet");

// Feature detection is hard...
// see https://gist.github.com/Kaiido/45d189c110d29ac2eda25a7762c470f2
// to get the list of all supported CanvasFilters
// below only checks for colorMatrix
function supportsColorMatrixCanvasFilter() 
  if(typeof CanvasFilter !== "function") 
    return false;
  
  let supported = false;
  try 
    new CanvasFilter(
      filter: "colorMatrix",
      // "type" will be visited for colorMatrix
      // we throw in to avoid actually creating the filter
      get type()  supported = true; throw ""; 
    );
   catch(err) 
  return supported;
&lt;canvas&gt;&lt;/canvas&gt;

【讨论】:

你是英雄,工作绝对完美,感谢您的快速帮助! 实际上,有一个小问题,如果“光”部分不是 100% 白色,它会应用透明的光覆盖,因此我最终会得到非常不同的颜色。但我想我们对此无能为力。 imgur.com/a/KhFJxMN 你可能会玩一点亮度和饱和度(两者都可以作为 CSS 过滤器,你可以在url(#... 之前设置)但没有通用的。 明白,再次感谢!

以上是关于arcgis js 4 使用d3.js 添加滤镜光的主要内容,如果未能解决你的问题,请参考以下文章

如何在 d3.js 中为颜色图例添加刻​​度线

d3.js 如何在条形图中添加线条

Renderer2 在使用 d3 js - Angular 4 时不渲染 SVG 元素

使用 D3 JS 将鱼眼添加到轴

d3.js学习

使用 d3.js 向饼图添加工具提示