首页 > 其他分享 >Mapboxgl Chrome75版本下发现问题:中文标签无法加载,由Canvas的measureText()方法导致

Mapboxgl Chrome75版本下发现问题:中文标签无法加载,由Canvas的measureText()方法导致

时间:2023-04-17 14:01:30浏览次数:37  
标签:Canvas const buffer Chrome75 js measureText mapbox gl glyphHeight

很刁钻的问题,排查了好久。

我自己开发测试用的浏览器(版本为112)运行正常,在老版本(75)谷歌浏览器报错如下:

mapbox-gl.js:32 Uncaught TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': Value is not of type 'long'.
    at Mp.TinySDF.draw (mapbox-gl.js:32)
    at Mp._tinySDF (mapbox-gl.js:32)
    at mapbox-gl.js:32
    at mapbox-gl.js:31
    at Array.forEach (<anonymous>)
    at M (mapbox-gl.js:31)
    at Mp.getGlyphs (mapbox-gl.js:32)
    at Jt.getGlyphs (mapbox-gl.js:36)
    at t.Actor.processTask (mapbox-gl.js:32)
    at t.Actor.receive (mapbox-gl.js:32)

起初以为是Mapboxgl的问题(虽然最终也确实是有一点关系),后来经过艰难排查发现是Canvas的measureText()方法在老版本谷歌浏览器中无法正常返回中文字符的宽度。
在Mapboxgl源码中出问题的部分在这里:

    draw(char) {
        const {
            width: glyphAdvance,
            actualBoundingBoxAscent,
            actualBoundingBoxDescent,
            actualBoundingBoxLeft,
            actualBoundingBoxRight
        } = this.ctx.measureText(char);  
	
        // The integer/pixel part of the top alignment is encoded in metrics.glyphTop
        // The remainder is implicitly encoded in the rasterization
        const glyphTop = Math.ceil(actualBoundingBoxAscent);
        const glyphLeft = 0;

        // If the glyph overflows the canvas size, it will be clipped at the bottom/right
        const glyphWidth = Math.max(0, Math.min(this.size - this.buffer, Math.ceil(actualBoundingBoxRight - actualBoundingBoxLeft)));
        const glyphHeight = Math.min(this.size - this.buffer, glyphTop + Math.ceil(actualBoundingBoxDescent));
        
        const width = glyphWidth + 2 * this.buffer;
        const height = glyphHeight + 2 * this.buffer;

        const len = Math.max(width * height, 0);
        const data = new Uint8ClampedArray(len);

        const glyph = {data, width, height, glyphWidth, glyphHeight, glyphTop, glyphLeft, glyphAdvance};
        if (glyphWidth === 0 || glyphHeight === 0) return glyph;

        const {ctx, buffer, gridInner, gridOuter} = this;
        ctx.clearRect(buffer, buffer, glyphWidth, glyphHeight);
        ctx.fillText(char, buffer, buffer + glyphTop);
        
        const imgData = ctx.getImageData(buffer, buffer, glyphWidth, glyphHeight);

        ...
    }

打印发现glyphWidth, glyphHeight是undefined。这几个值由最上面的actualBoundingBoxAscent, actualBoundingBoxDescent, actualBoundingBoxLeft, actualBoundingBoxRight计算得来,而这四个值在对象是中文字符时没有正常返回,从而导致整个绘制流程出错,结果表现就是带有中文字符标签(text-field)的symbol图层无法加载。

解决办法:

  1. 规避。升级浏览器,或避免标签出现中文。
  2. 修改该部分源码,在测量方法不能正常返回值时给glyphWidth和glyphHeight默认值,这样也可以绘制出中文标签

标签:Canvas,const,buffer,Chrome75,js,measureText,mapbox,gl,glyphHeight
From: https://www.cnblogs.com/cosmicbison/p/17325637.html

相关文章

  • vue pc使用htmlCanvas Jspdf 实现点击将页面生成图片并转成pdf下载
    <template><divid="main"ref="workbench"v-loading="loading"class="echartsPdf">需要的内容</div></template><script>importhtml2canvasfrom'html2canvas'importJspdf......
  • HTML5 Canvas和SVG的区别
    Canvas主要是用笔刷来绘制2D图形的。SVG主要是用标签来绘制不规则矢量图的。相同点:都是主要用来画2D图形的。区别:SVG画的是矢量图,Canvas画的是位图;SVG节点过多时渲染慢,Canvas性能更好一点,但写起来更复杂;SVG支持分层和事件,Canvas不支持,但是可以用库实现。......
  • power apps canvas 最新scan 扫描功能 barcode, QR code
    Barcodereader现在全面代替barcode scanner barcodereader现在只能通过powerappsmobileapp或者powerappsWindowsUWPapp来使用。还不能通过浏览器使用      Barcodereader控件支持下面数据类型   barcodereader控件和scanner最大的区......
  • Power Apps Canvas Modern Controls
    Canvas的“丑”一直被人诟病,但是新的moderncontrol基于fluentUI给大家一种回到现代的感觉。https://powerapps.microsoft.com/en-us/blog/modern-controls-coming-to-canvas-apps/新的moderncontrols有这么一些好处现代–一种专注且简洁的设计,支持更丰富的交互状态和层......
  • canvas基础4
    canvas基础4一、图案//图案是用于填充和描画图形的重复图像。//要创建新图案,可以调用createPattern()方法并传入两个参数。letimage=newImage();image.src=star.png;pattern=context.createPattern(image,"repeat");//画一个矩形context.fillStyle=patte......
  • canvas基础3
    canvas基础3一、绘制图像//2d绘图上下文内置支持操作图像。//如果想把现有图像绘制到画布上,可以使用drawImage()方法。//context.drawImage(图像,x坐标,y坐标);context.drawImage(image,10,10);//context.drawImage(图像,x坐标,y坐标,图像宽度,图像高度);......
  • canvas基础2
    canvas基础2一、绘制路径//2d绘图上下文支持很多在画布上绘制路径的方法。//通过路径可以创建复杂的形状和线条。letdrawing=document.getElementById("drawing");//确保完全支持<canvas>if(drawing.getContext){letcontext=drawing.getContext("2d"......
  • canvas实现图片镜像翻转的2种方式
    canvas实现图片镜像翻转的2种方式原文引用:https://www.qetool.com/scripts/view/23387.html1.通过canvas自带的画布方法进行翻转varimg=newImage();//这个就是img标签的dom对象img.src='./sy.png';img.onload=function(){//图片加载完成后,执行此方......
  • canvas基础1
    canvas基础1一、canvas是HTML5提供的画画本//创建<canvas>元素时至少要设置其width和height属性,这样才能告诉浏览器在大面积上绘图。//出现在开始和结束标签之间的内容是后备数据,会在浏览器不支持<canvas>元素时显示。<canvasid="drawing"width="200"height=......
  • canvas绘制3D金字塔
    varcanvas1=document.getElementById("canvas1");varcontext=canvas1.getContext("2d");canvas1.width=400;canvas1.height=400;context.beginPath();context.moveTo(0,360);context.lineTo(200,400);context.lineTo(400,360)......