【问题标题】:Wrapping a text around an image in a Canvas在画布中围绕图像环绕文本
【发布时间】:2013-07-02 07:24:11
【问题描述】:

是否可以在 HTML 5 Canvas 内的图像周围环绕文本?例如使用一些 Javascript 框架?我查看了 KineticJS,但找不到有用的东西。

编辑:

看来我的问题不清楚。我正在寻找类似的东西:

http://www.monkeydoit.com/images/panda2.gif

【问题讨论】:

    标签: html image text canvas javascript-framework


    【解决方案1】:

    您可以使用画布变换(平移+旋转)将文本环绕在图像(矩形)周围

    例如,这是您旋转画布并在图像右侧向下绘制文本的方式:

    // save the untransformed state of the context
    ctx.save();
    
    // translate to the top-right corner of the image
    // ( x/y properties have been added to the standard img element )
    ctx.translate(image.x+image.width,image.y);
    
    // rotate the canvas 90 degrees (PI/2 radians)
    ctx.rotate(Math.PI/2);
    
    // the canvas is now properly moved and rotated
    // so we can just draw the text at [0,0]
    ctx.fillText(subtext,0,0);
    
    // restore the context to its untransformed state
    ctx.restore();
    

    这会使用 context.measureText 计算有多少单词适合一边:

    var end=0;
    
    var subtext="";
    
    while(ctx.measureText(text.split(" ",end+1).join(" ")).width<=length)
    {
        subtext=text.split(" ",end+1).join(" ");
        end++;
    }
    

    一个有趣的改进是在圆角矩形周围绘制文本。

    这是代码和小提琴:http://jsfiddle.net/m1erickson/U2hE3/

    <!doctype html>
    <html>
    <head>
    <link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
    <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
    
    <style>
        body{ background-color: ivory; padding:10px; }
        canvas{border:1px solid red;}
    </style>
    
    <script>
    $(function(){
    
        var canvas=document.getElementById("canvas");
        var ctx=canvas.getContext("2d");
    
        var rect={x:40,y:40,width:150,height:120};
    
        var text="This is some text that wraps on the outside of a rectangle.";
    
        var font="14px Verdana";
    
        drawTextAroundRect(rect,text,7,font);
    
    
        function drawTextAtAngle(text,length,x,y,radians){
    
            // if text is empty then return
            if(text.length==0){return;}
    
            var end=0;
            var subtext="";
    
            if(ctx.measureText(text).width<=length){
    
                // all the text fits
                subtext=text; 
    
            }else{
    
                // calc how many words will fit on this length
                while(ctx.measureText(text.split(" ",end+1).join(" ")).width<=length)
                {
                    subtext=text.split(" ",end+1).join(" ");
                    end++;
                }
    
            }
    
            // draw the text at the appropriate angle
            ctx.save();
            ctx.translate(x,y);
            ctx.rotate(radians);
            ctx.fillText(subtext,0,0);
            ctx.restore();
    
            // return any text that didn't fit for further processing
            if(end==text.length){
                return("");
            }else{
                return(text.substr(subtext.length));
            }
    
        }
    
    
        function drawTextAroundRect(rect,text,textPadding,font){
    
            // set the font
            ctx.font=font;
    
            // top
            text=drawTextAtAngle(text,rect.width,rect.x,rect.y-textPadding,0);
    
            // right
            text=drawTextAtAngle(text,rect.height,rect.x+rect.width+textPadding,rect.y,Math.PI/2);
    
            // bottom
            text=drawTextAtAngle(text,rect.width,rect.x+rect.width,rect.y+rect.height+textPadding,Math.PI);
    
            // left
            text=drawTextAtAngle(text,rect.height,rect.x-textPadding,rect.y+rect.height,Math.PI*1.5);
    
            // draw the rect (just for illustration)
            ctx.beginPath();
            ctx.rect(rect.x,rect.y,rect.width,rect.height);
            ctx.stroke();
    
        }
    
    
    }); // end $(function(){});
    </script>
    
    </head>
    
    <body>
        <canvas id="canvas" width=300 height=250></canvas>
    </body>
    </html>
    

    [根据提问者的说明添加更多自动换行代码]

    您可以使用 context.measureText 来获取文本的宽度,并使用它来将文本环绕在图像周围。

    给定文本宽度,当文本超出所需宽度时,您可以通过前进到下一行来构建自动换行。

    在环绕图片的情况下,您将有 2 个所需的宽度 - 文本可能会进入图像时更短,之后则更长。

    这是代码和小提琴:http://jsfiddle.net/m1erickson/XM5Yp/

    <!doctype html>
    <html>
    <head>
    <link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
    <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
    
    <style>
        body{ background-color: ivory; }
        canvas{border:1px solid red;}
    </style>
    
    <script>
    $(function(){
    
        var canvas=document.getElementById("canvas");
        var ctx=canvas.getContext("2d");
    
        var maxWidth = 350;
        var lineHeight = 25;
        var x = (canvas.width - maxWidth) / 2;
        var y = 60;
        var text = "'Twas the night before Christmas, when all through the house.  Not a creature was stirring, not even a mouse.  The stockings were hung by the chimney with care in hopes that St. Nicholas soon would be there.";
    
        ctx.font = '16pt Calibri';
        ctx.fillStyle = '#333';
    
        var imgWidth;
        var imgHeight;
    
        var img=new Image();
        img.onload=function(){
    
            imgWidth=img.width;
            imgHeight=img.height;
    
            ctx.drawImage(img,canvas.width-img.width,0)
    
            wrapText(text, x, y, maxWidth, lineHeight);
    
        }
        img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house204-1.jpg";
    
    
        function wrapText(text, x, y, maxWidth, lineHeight) {
    
          var words = text.split(' ');
          var line = '';
    
          var maxLineWidth=y>imgHeight+10?maxWidth:maxWidth-imgWidth;
    
          for(var n = 0; n < words.length; n++) {
            var testLine = line + words[n] + ' ';
            var metrics = ctx.measureText(testLine);
            var testWidth = metrics.width;
            if(testWidth > maxLineWidth) {
              ctx.fillText(line, x, y);
              line = words[n] + ' ';
              y += lineHeight;
              maxLineWidth= y>imgHeight+10?maxWidth:maxWidth-imgWidth;
    
            }
            else {
              line = testLine;
            }
          }
          ctx.fillText(line, x, y);
        }
    
    }); // end $(function(){});
    </script>
    
    </head>
    
    <body>
        <canvas id="canvas" width=400 height=325></canvas>
    </body>
    </html>
    

    【讨论】:

    • 哎哟……误会了! :p -- 但感谢您的澄清。我在原始答案中添加了另一个适合您需求的解决方案。顺便说一句,为什么不直接使用 div 元素,添加段落并向右浮动熊猫图像?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多