fabricjs / fabric.js

Javascript Canvas Library, SVG-to-Canvas (& canvas-to-SVG) Parser
http://fabricjs.com
Other
28.74k stars 3.49k forks source link

Masking an image to a multi-line textbox does not work properly #7708

Closed hoomanaskari closed 2 years ago

hoomanaskari commented 2 years ago

Hi,

I am trying to mask an image to a textbox, If I have a text box with a single line, it works, but the moment the textbox becomes multi-lined it disappears, I tried to debug but have no clue why it happens, everything seems to be normal.

Try this fiddle: https://jsfiddle.net/hoomanaskari/jf093qgm/

Enable the code on line 18 globalCompositeOperation: "destination-in" and you can see the everything disappears. now if you enable line 17 width: 500 and play around with width to make the text a 1 liner, it will reappear.

Exactly the same issue if I try it with a text on path.

Thanks in advance.

ShaMan123 commented 2 years ago

I guess you came across a group issue If you don't need group this is your solution: https://jsfiddle.net/qtwf5sz6/8/

If you do #7670

ShaMan123 commented 2 years ago

If this satisfies you feel free to close

hoomanaskari commented 2 years ago

Thank you very much, I think I'll have to wait until v6.0 is released for this one to be resolve.

ShaMan123 commented 2 years ago

You can try it out, it's pretty stable

hoomanaskari commented 2 years ago

Oh that sounds great, I'll definitely give it go.

carior commented 1 year ago

i have same question! If I want to change lines, what should I do? var canvas = new fabric.Canvas('c'); const imgurl1 = 'https://cdn.qimao.com/bookimg/zww/upload/cover/tpl/source/BBY32.jpg' const imgurl2 = 'https://cdn.qimao.com/bookimg/zww/upload/cover/specialwords/pattern/AW8.jpg' // 材质 const imgurl3 = 'https://cdn.qimao.com/bookimg/zww/upload/cover/specialwords/material/AW8.png' // 素材 const imgurl4 = 'https://cdn.qimao.com/bookimg/zww/upload/cover/specialwords/material/AW6.png' // 素材2

  // 创建图片底图
  fabric.Image.fromURL(
      imgurl1,
      img => {
          canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas), {
              repeat: 'repeat',
          })
      }
  )

  // 创建黑色不透明材质
  const imgEl = document.createElement('img');
  imgEl.src = imgurl2
  // 插入页面
  document.body.appendChild(imgEl);
  imgEl.onload = () => {
      // 创建图片对象
      const imgInstance = new fabric.Image(imgEl, {
          name: 'pic',
          selectable: false,
          globalAlpha: 0.1
      },{ crossOrigin: 'anonymous' });
      // canvas.add(imgInstance)
      // canvas.add(text);
      text.left = (imgEl.width - text.width) / 2
      text.top = (imgEl.height - text.height) / 2
      canvas.renderAll()
      // 删除页面中的图片元素
      imgEl.remove()

      // 这里不能使用组,否则换行的文字不显示
      var group = new fabric.Group([imgInstance, text], {
          selectable: false
      })
      canvas.add(group);
  }

  // 创建文本 // 目标图像 新的
  // var text = new fabric.Textbox('如何做出好看的如何做\n出好看的如何\n如何做撒打算打算', {
  var text = new fabric.Textbox('如何做出的如何', {
      fontSize: 68,
      left: 0,
      top: 0,
      splitByGrapheme: false,
      fontFamily: 'test-family',
      // 源图像:旧的, 目标:新的 ,
      globalCompositeOperation: 'destination-in', // 在源图像中显示目标图像。只有源图像内的目标图像部分会被显示,源图像是透明的。 在深色材质上,显示文字,只有深色图像内的文字才会被现实,材质是透明的
  });

  // 创建素材 图像源 已经存在的
  const imgEl3 = document.createElement('img');
  imgEl3.src = imgurl3
  // 插入页面
  document.body.appendChild(imgEl3);
  imgEl3.onload = () => {
      // 创建图片对象
      const imgInstance = new fabric.Image(imgEl3, {
          name: 'pic',
          left: 0, 
          top: 0,
          crossOrigin: 'anonymous'
      });
      canvas.add(imgInstance)
      canvas.renderAll()
      // 删除页面中的图片元素
      imgEl3.remove()
  }
ShaMan123 commented 1 year ago

i have same question! If I want to change lines, what should I do?

That isn't clear enough I suggest you open a new discussion linking to this one

ShaMan123 commented 1 year ago

If I am here there is another option which is subclassing _render or drawObject and applying masking there. One day when we rebuild the website I will write a post about custom rendering

carior commented 1 year ago

i have same question! If I want to change lines, what should I do?

That isn't clear enough I suggest you open a new discussion linking to this one

I'm sorry, this is the case. TextBox not displayed,Please look at it for me. Thank you! https://jsfiddle.net/carior/w76cxasz/7/

ShaMan123 commented 1 year ago

https://jsfiddle.net/8cneqdmx/

globalCompositeOperation

carior commented 1 year ago

https://jsfiddle.net/8cneqdmx/

globalCompositeOperation sorry,Your revision did not achieve my purpose!

image

1.Only the text part of the picture needs to be shown, the rest of the picture is transparent

2.The text should be centered

3.I have tried to use pattern to achieve, but it is not easy to center

That's what it should look like

image
ShaMan123 commented 1 year ago

not exactly sure why GCO wasn't working, maybe is a text rendering thing https://jsfiddle.net/ex9zo8mp/ using caching solves it

ShaMan123 commented 1 year ago

OHH Sure! without caching the text is rendered letter by letter. With GCO destination-in it must have an overlap, but letters never overlap so nothing remained on canvas

w/o object caching https://jsfiddle.net/9La5pqek/1/

carior commented 1 year ago

Thank you very much for your answer