Редактирование изображения с линейным градиентом и преобразование в base64 React

#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:

  1. import { createCanvas, Image } from 'canvas' предназначено для версии 1.x библиотеки, как описано здесь . Скорее всего, вы используете 2.x.
  2. «Испорченные холсты не могут быть экспортированы». означает, что вы загрузили междоменное изображение в холст. Поэтому вы не можете вызвать 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) в третьем методе . Но я не знаю, что происходит сейчас, потому что изображение возвращается следующим образом: пример . Я хочу, чтобы эффект был на изображении, а не поверх изображения. Вы знаете, как это сделать, Серджиу?