React IconTint(画布)动态改变颜色
Posted
技术标签:
【中文标题】React IconTint(画布)动态改变颜色【英文标题】:React IconTint (canvas) change color dynamically 【发布时间】:2021-12-17 00:09:49 【问题描述】:有没有办法从react-icon-tint
库中动态更改<IconTint />
元素的颜色?
我需要在 isActive
状态更改时更改颜色,但它看起来不像我预期的那样工作,因为它在引擎盖下使用了 canvas
元素。
我还尝试重新渲染isActive
上的整个元素,像这样改变
isActive ? (
<IconTint src=getCustomIcon() color=icon />
) : (
<IconTint src=getCustomIcon() color=iconOnBackground />
);
但它也没有工作。
【问题讨论】:
【参考方案1】:我查看了源代码,因为它是一个记忆化组件,它不会在父级重新渲染时重新渲染,并且因为在组件内部使用的 useEffect 内部,不包括颜色和图像 src 等依赖项,它确实不重新渲染道具更改,显然这是一个错误或不受欢迎的行为。我不知道为什么你的做法不起作用,因为这两个 IconTint 组件是两个不同的组件!但你可以这样做:
isActive && <IconTint src=getCustomIcon() color='#0000ff' />
!isActive && <IconTint src=getCustomIcon() color='#b43285' />
我不认为这是高性能的,源代码是如此简单,所以你可以在你的项目中实现 IconTint 并在 useEffect 依赖数组中添加依赖。这里我提供了修改后的版本。
import React, memo, useEffect, useRef, useState from "react";
import PropTypes from "prop-types";
const IconTint = ( fallback = <span />, src, color, maxWidth, maxHeight ) =>
const canvasRef = useRef(null);
const [size, setSize] = useState();
const _scaleImage = (srcWidth, srcHeight, maxWidth, maxHeight) =>
if (maxWidth && maxHeight)
const ratio = Math.min(maxWidth / srcWidth, maxHeight / srcHeight);
return width: srcWidth * ratio, height: srcHeight * ratio ;
if ((maxWidth && !maxHeight) || (!maxWidth && maxHeight))
throw new Error(
"If you are going to provide width, make sure to provide height as well"
);
return width: srcWidth, height: srcHeight ;
;
useEffect(() =>
const canvas = canvasRef.current;
// eslint-disable-next-line no-undef
const pic = new Image();
pic.src = src;
const tintCanvas = document.createElement("canvas");
const tintCtx = tintCanvas.getContext("2d");
const ctx = canvas.getContext("2d");
pic.onload = () =>
const result = _scaleImage(pic.width, pic.height, maxWidth, maxHeight);
setSize(result);
tintCanvas.width = result.width;
tintCanvas.height = result.height;
tintCtx.fillStyle = color;
tintCtx.fillRect(0, 0, result.width, result.height);
tintCtx.globalCompositeOperation = "destination-atop";
tintCtx.drawImage(pic, 0, 0, result.width, result.height);
ctx.globalAlpha = 1;
ctx.drawImage(tintCanvas, 0, 0, result.width, result.height);
;
, [src,color,maxHeight,maxWidth]);
if (
typeof window !== "undefined" &&
window.document &&
window.document.createElement
)
return <canvas width=size.width height=size.height ref=canvasRef />;
return fallback;
;
IconTint.propTypes =
src: PropTypes.string.isRequired,
color: PropTypes.string.isRequired,
fallback: PropTypes.node,
maxWidth: PropTypes.number,
maxHeight: PropTypes.number
;
export default memo(IconTint);
现在您可以像这样使用这个修改后的版本:
<IconTint src=getCustomIcon() color=isActive ? '#0000ff' : "#b43285"/>
【讨论】:
以上是关于React IconTint(画布)动态改变颜色的主要内容,如果未能解决你的问题,请参考以下文章