我需要帮助修复代码以防止 Iphone 图像闪烁。我已经实现了各种东西,例如 useMemo 和 useLayout 和 debounce 和
requestAnimationFrame
但我仍然面临问题
// i have imported useMemo, useRef, useCallback from React
import React, { useState, useMemo, useRef, useCallback } from "react";
import "./Iphone.css";
// I have imported debounce from lodash
import debounce from "lodash.debounce";
// I have created functional component called IPhone
const Iphone = () => {
// I have used selectedImage and OldImage variable here and initialized them to `null`
// I have used useMemo on initial loading of page to prevent flashing
const image = useMemo(() => new Image(), []);
// I have used useCallback function on initial loading of the page to handleImageChange function
// to change a image I called handleImageChange function
const handleImageChange = useCallback((event) => {
event.preventDefault();
const newImageURL = URL.createObjectURL(event.target.files[0]);
// i have passed newIMageURL to both SetSelectedImage and SetOldImage
setSelectedImage(newImageURL);
setOldImage(newImageURL);
}, []);
// I have called the function handleText to toggle showing of text
const handleText = () => {
setShowText(!showText);
};
// I have called useMemo function to prevent flashing as i drag the text to
various
locations
const debouncedShowContent = useMemo(
() => debounce((value) => setContent(value), 300),
[]
);
// i have called useCallback function to prevent flashing in handleDragStart
function
const handleDragStart = useCallback(() => {
// here I am setting dragging to true as i am starting to drag the text
setDragging(true);
}, []);
// I have called useCallback function to prevent flashing in handleDrag function
const handleDrag = useCallback(
(e) => {
// i am checking if dragging is true
if (dragging) {
// i am calling requestAnimation Frame here
requestAnimationFrame(() => {
// I am getting value of canvas via canvasRef.current
const canvas = canvasRef.current;
// i am saving value in ctx
const ctx = canvas.getContext("2d");
// i am getting dimensions using canvas.getBoundingClientRect and saving it
in rect
const rect = canvas.getBoundingClientRect();
// i am getting value of e.clientX - rect.left and saving it in x variable
const x = e.clientX - rect.left;
// i am getting value of e.clientY - rect.top and saving it in y variable
const y = e.clientY - rect.top;
// clearing the values of ctx via ctx.clearRect
ctx.clearRect(0, 0, canvas.width, canvas.height);
// i am inserting value into image the value oldImage
image.src = oldImage;
// on loading of image i am setting value in canvas
image.onload = () => {
// drawing image using ctx.drawImage
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
// i am using ctx.fillText to fill the text with value of content and x and
y
ctx.fillText(content, x, y);
I am setting position of x and y via setPosition
setPosition({ x, y });
// converting the value of image to text
const dataURI = canvas.toDataURL("image/png");
// saving in setSelectedImage the value of dataURI
setSelectedImage(dataURI);
};
});
}
},
[dragging, oldImage, content]
);
// i have called useCallback function to prevent flashing in handleDragEnd
function
const handleDragEnd = useCallback(() => {
// i am setting the position in x and y via position.x and position.y
setPosition({ x: position.x, y: position.y });
// i am setting dragging to false
setDragging(false);
}, [position]);
// i have called useCallback function to prevent flashing in addText function
const addText = useCallback(() => {
// here i am setting the image to be true
setShowImage(true);
// if image is not selected then do return;
if (!selectedImage || !content) return;
textDrawn.current = true;
requestAnimationFrame(() => {
// I am getting value of canvas via canvasRef.current
const canvas = canvasRef.current;
// i am saving value in ctx
const ctx = canvas.getContext("2d");
// i am inserting value into image the value selectedImage
image.src = selectedImage;
// on loading of image i am setting value in canvas
image.onload = () => {
// getting width of canvas from image.width
canvas.width = image.width;
// getting height of canvas from image.height
canvas.height = image.height;
// clearing the values of ctx via ctx.clearRect
ctx.clearRect(0, 0, canvas.width, canvas.height);
// drawing image using ctx.drawImage
ctx.drawImage(image, 0, 0);
// i am using ctx.fillText to fill the text with value of content
ctx.fillText(content, textPosition.x, textPosition.y);
// converting the value of image to text
const dataURI = canvas.toDataURL("image/png");
// saving in setSelectedImage the value of dataURI
setSelectedImage(dataURI);
};
});
}, [selectedImage, content, textPosition]);
// i have used debouncedShowContent function to prevent flashing in showContent
function
const showContent = (event) => {
// calling debouncedShowContent
debouncedShowContent(event.target.value);
};
// I am using handleSave function to save the image along with text in new
window
const handleSave = () => {
// if image is selected then I am opening new window
if (selectedImage) {
// opening a new window
const newWindow = window.open();
// writing a new image
newWindow.document.write(
`<img src="${selectedImage}" alt="resultingImage" />`
);
}
};
// i want to add more details. if you have any questions ask and i will clarify
quickly.
};
// I am exporting the Iphone function
export default Iphone;
当我将文本从一个位置拖动到另一个位置时,我想防止图像闪烁。怎么办?
我可以添加更多细节。如果您有任何疑问,请提出,我会尽快澄清。
我已经在每一行代码中发表了注释。我还应该做些什么来改善这个问题吗?
我将重点关注
handleDrag
功能...
删除所有评论,这就是我们得到的:
requestAnimationFrame(() => {
const canvas = canvasRef.current;
const ctx = canvas.getContext("2d");
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
ctx.clearRect(0, 0, canvas.width, canvas.height);
image.src = oldImage;
image.onload = () => {
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
ctx.fillText(content, x, y);
setPosition({ x, y });
const dataURI = canvas.toDataURL("image/png");
setSelectedImage(dataURI);
};
});
首先突出的是常量
canvas
、ctx
和 rect
,您应该将它们移至全局常量,无需每次调用拖动函数或与绘图相关的任何其他函数时都实例化它们
其次,这个函数中有
image.onload
,我不认为oldImage
每次都会改变值,最好在这个函数之外执行此操作,使图像成为全局常量