Реагируйте на печать значка (холст) динамично меняйте цвет

#javascript #html #reactjs #html5-canvas

Вопрос:

Есть ли способ динамически изменять цвета lt;IconTint /gt; элемента из react-icon-tint библиотеки? Мне нужно, чтобы цвет менялся при isActive изменении состояния, но, похоже, он работает не так, как я ожидал, потому что он использует canvas элемент под капотом.

Я также попытался перенаправить весь элемент на isActive изменение таким образом

 {  isActive ? (  lt;IconTint src={getCustomIcon()} color={icon} /gt;  ) : (  lt;IconTint src={getCustomIcon()} color={iconOnBackground} /gt;  ); }  

Но и это тоже не сработало.

Ответ №1:

Я просмотрел исходный код, потому что это компонент с памятью, он не повторяется при повторной передаче родительского кода, и поскольку внутри эффекта использования, используемого внутри компонента, зависимости, такие как src цвета и изображения, не включены, он не повторяется при изменении реквизита, очевидно, это ошибка или нежелательное поведение. Я не знаю, почему ваш способ сделать это не работает, потому что эти два компонента IconTint-это два разных компонента!. но вы можете сделать это таким образом:

 {isActive amp;amp; lt;IconTint src={getCustomIcon()} color='#0000ff' /gt;}  {!isActive amp;amp; lt;IconTint src={getCustomIcon()} color='#b43285' /gt;}  

Я не думаю, что это эффективно, исходный код настолько прост, что вы можете реализовать IconTint внутри своего проекта и просто добавить зависимости внутри массива зависимостей useEffect. Здесь я предоставил измененную версию.

 import React, { memo, useEffect, useRef, useState } from "react"; import PropTypes from "prop-types";  const IconTint = ({ fallback = lt;span /gt;, src, color, maxWidth, maxHeight }) =gt; {  const canvasRef = useRef(null);  const [size, setSize] = useState({});   const _scaleImage = (srcWidth, srcHeight, maxWidth, maxHeight) =gt; {  if (maxWidth amp;amp; maxHeight) {  const ratio = Math.min(maxWidth / srcWidth, maxHeight / srcHeight);  return { width: srcWidth * ratio, height: srcHeight * ratio };  }  if ((maxWidth amp;amp; !maxHeight) || (!maxWidth amp;amp; maxHeight)) {  throw new Error(  "If you are going to provide width, make sure to provide height as well"  );  }  return { width: srcWidth, height: srcHeight };  };   useEffect(() =gt; {  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 = () =gt; {  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" amp;amp;  window.document amp;amp;  window.document.createElement  ) {  return lt;canvas width={size.width} height={size.height} ref={canvasRef} /gt;;  }  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);  

теперь вы можете использовать эту измененную версию следующим образом:

 lt;IconTint src={getCustomIcon()} color={isActive ? '#0000ff' : "#b43285"}/gt;