#javascript #node.js #reactjs #react-hooks #frontend
#javascript #node.js #reactjs #реакция-хуки #интерфейс
Вопрос:
Я использую библиотеку «canvas» для редактирования изображения (по URL) с помощью linear-gradient, и я использую некоторые методы. Но я пока не могу получить правильные результаты.
Я использовал эти методы с canvas, но с React все работает хорошо. Знаете ли вы другой способ отредактировать изображение с линейным градиентом и преобразовать его в base64?
Первый метод
import { loadImage, createCanvas } from 'canvas'
useEffect(() => {
const coversheet = 'https://...'
const canvas = createCanvas('600', '286')
const ctx = canvas.getContext('2d')
loadImage(coversheet).then( image => {
ctx.drawImage(image, 340, 515, 70, 70)
let gradient = ctx.createLinearGradient(0, 0, 170, 0)
gradient.addColorStop(0, 'white')
gradient.addColorStop(1, 'red')
ctx.fillStyle = gradient
ctx.fillRect(20, 20, 150, 100)
})
let base64 = canvas.toDataURL('image/jpeg')
setCoversheetSrc(base64)
}, [])
С помощью этого метода я ничего не получаю, это возвращает черное изображение (оно черное, когда используется тип «image / jpeg») в base64.
Второй способ
import { createCanvas, Image } from 'canvas'
useEffect(() => {
const coversheet = 'https://...'
const canvas = createCanvas('600', '286')
const ctx = canvas.getContext('2d')
const img = new Image()
img.crossOrigin = 'Anonymous'
img.onload = () => {
ctx.drawImage(this, 340, 515, 70, 70)
let gradient = ctx.createLinearGradient(0, 0, 170, 0)
gradient.addColorStop(0, 'white')
gradient.addColorStop(1, 'red')
ctx.fillStyle = gradient
ctx.fillRect(20, 20, 150, 100)
}
img.src = coversheet
let base64 = canvas.toDataURL()
setCoversheetSrc(base64)
}, [])
С помощью этого кода я получаю это сообщение об ошибке:
Ошибка типа: canvas__WEBPACK_IMPORTED_MODULE_2__.Изображение не является конструктором.
Указывая на эту строку «const img = new Image()»
Третий способ:
import { loadImage, createCanvas } from 'canvas'
useEffect(() => {
const runCanvas = async () => {
const coversheet = 'https://...'
const canvas = await createCanvas('600', '286')
const ctx = await canvas.getContext('2d')
const image = await loadImage(coversheet)
ctx.drawImage(image, 340, 515, 70, 70)
let gradient = ctx.createLinearGradient(0, 0, 170, 0)
gradient.addColorStop(0, 'white')
gradient.addColorStop(1, 'red')
ctx.fillStyle = gradient
ctx.fillRect(20, 20, 150, 100)
let base64 = await canvas.toDataURL('image/jpeg')
setCoversheetSrc(base64)
}
runCanvas()
}, [])
При этом я получаю эту ошибку:
Необработанное отклонение (SecurityError): не удалось выполнить ‘toDataURL’ на ‘HTMLCanvasElement’: испорченные холсты не могут быть экспортированы.
Ответ №1:
import { createCanvas, Image } from 'canvas'
предназначено для версии 1.x библиотеки, как описано здесь . Скорее всего, вы используете 2.x.- «Испорченные холсты не могут быть экспортированы». означает, что вы загрузили междоменное изображение в холст. Поэтому вы не можете вызвать
toDataURL
его, как задокументировано, по соображениям безопасности.
Вам нужно будет либо добавить соответствующие заголовки CORS в этот ответ на изображение, либо, если сервер не находится под вашим контролем, вы можете альтернативно проксировать его через свой собственный и обслуживать его с соответствующими заголовками CORS. Они должным образом задокументированы здесь .
Комментарии:
1.Около 1. Я изменил версию на 1.x, но теперь она выдает эту ошибку при импорте библиотеки. Ошибка типа: не удается установить для свойства ‘parseFont’ значение undefined около 2. У меня есть контроль на сервере, вопрос… Есть ли другой способ настроить crossOrigin, как во втором методе, но без конструктора Image() ?
2. @LuisCarlos Да, вы можете, посмотрите на это: developer.mozilla.org/en-US/docs/Web/HTML/Element /…
3. Это работает! Я просто написал
image.crossOrigin = 'Anonymous
после строкиconst image = await loadImage(coversheet)
в третьем методе . Но я не знаю, что происходит сейчас, потому что изображение возвращается следующим образом: пример . Я хочу, чтобы эффект был на изображении, а не поверх изображения. Вы знаете, как это сделать, Серджиу?