2017-06-11 7 views
0

キャンバス内に挿入する大きなテキストがあります。キャンバス内にスクロール可能なテキストを作成する

最初にテキストを折り返して、キャンバス内でスクロール可能にしようとしています。

context.wrapText = function(text, x, y, maxWidth, lineHeight) { 
    var y_initial = y; 
    var cars = text.split("\n"); 
    for (var ii = 0; ii < cars.length; ii++) { 
     var line = ""; 
     var words = cars[ii].split(" "); 
     for (var n = 0; n < words.length; n++) { 
      var testLine = line + words[n] + " "; 
      var metrics = context.measureText(testLine); 
      var testWidth = metrics.width; 
      if (testWidth > maxWidth) { 
       context.fillText(line, x, y); 
       line = words[n] + " "; 
       y += lineHeight; 
      } 
      else { 
       line = testLine; 
      } 
     } 
     context.fillText(line, x, y); 
     y += lineHeight; 
    } 
    return y - y_initial; 
} 

context.wrapText("hello dear friends\nhere is\na sample of text\nthis is juste an example\nthanks\nbut need to be scrollable\n it works?\nlet's try.", 120, 80, 200, 15); 

ご協力いただきありがとうございます。

答えて

1

キャンバスは単なるピクセルストアです。ピクセルを除いて描画されるものは覚えていません。スクロールボックスを実行するには、移動するたびにスクロールボックス全体をレンダリングする必要があります。

コンテキストを使用すると、クリップ領域を設定できます。境界線を越えるテキストが表示されていないことを確認するために使用します。

ctx.setTransformを使用して、レンダリングのスクロール位置を設定します。上にスクロールする場合、スクロール位置は負の値に移動する必要があります。

デモは、テキストスクロールボックスの非常に基本的な例です。それは最適化されておらず、テキストフィッティングには真のスマートはありません。

詳細については、コードを参照してください。かなり基本的なコードなので、多くのコメントはありません。コメントがあれば質問してください。

私はあなたに任せているマウスやユーザーの操作はありません。

const ctx = canvas.getContext("2d"); 
 

 
const textScrollBox = { 
 
    dirty : true, // indicates that variouse setting need update 
 
    cleanit(dontFitText){ 
 
     if(this.dirty){ 
 
      this.setFont(); 
 
      this.getTextPos(); 
 
      this.dirty = false; 
 
      if(!dontFitText){ 
 
       this.fitText(); 
 
      } 
 
     }   
 
    }, 
 
    scrollY : 0, 
 
    fontSize : 24, 
 
    font : "Arial", 
 
    align : "left", 
 
    background : "#999", 
 
    border : { 
 
     lineWidth : 4, 
 
     style : "black", 
 
     corner : "round", 
 
    }, 
 
    scrollBox : { 
 
     width : 10, 
 
     background : "#568", 
 
     color : "#78a", 
 
    }, 
 
    fontStyle : "black", 
 
    setOptions(options){ 
 
     Object.keys(this).forEach((key) =>{ 
 
      if(options[key] !== undefined){ 
 
       this[key] = options[key]; 
 
       this.dirty = true; 
 
      } 
 
     }) 
 
    }, 
 
    setFont(){ 
 
     this.fontStr = this.fontSize + "px " + this.font; 
 
     this.textHeight = this.fontSize + Math.ceil(this.fontSize * 0.05); 
 
    }, 
 
    getTextPos(){ 
 
     if(this.align === "left"){ this.textPos = 0 } 
 
     else if(this.align === "right"){ this.textPos = Math.floor(this.width - this.scrollBox.width -this.fontSize/4) } 
 
     else { this.textPos = Math.floor((this.width- - this.scrollBox.width)/2) } 
 
    }, 
 
    fitText(){ 
 
     this.cleanit(true); // MUST PASS TRUE or will recurse to call stack overflow 
 

 
     ctx.font = this.fontStr; 
 
     ctx.textAlign = this.align; 
 
     ctx.textBaseline = "top"; 
 
     var words = this.text.split(" "); 
 
     this.lines.length = 0; 
 
     var line = ""; 
 
     var space = ""; 
 
     while(words.length > 0){ 
 
      var word = words.shift(); 
 
      var width = ctx.measureText(line + space + word).width; 
 
      if(width < this.width - this.scrollBox.width - this.scrollBox.width){ 
 
       line += space + word; 
 
       space = " "; 
 
      }else{ 
 
       if(space === ""){ // if one word too big put it in anyways 
 
        line += word; 
 
       }else{ 
 
        words.unshift(word); 
 
       } 
 
       this.lines.push(line); 
 
       space = ""; 
 
       line = ""; 
 
      } 
 
     } 
 
     if(line !== ""){ 
 
      this.lines.push(line); 
 
     } 
 
     this.maxScroll = ((this.lines.length + 0.5) * this.textHeight) - this.height; 
 
    },    
 
    drawBorder(){ 
 
     var bw = this.border.lineWidth/2; 
 
     ctx.lineJoin = this.border.corner; 
 
     ctx.lineWidth = this.border.lineWidth; 
 
     ctx.strokeStyle = this.border.style; 
 
     ctx.strokeRect(this.x - bw,this.y - bw,this.width + 2 * bw,this.height + 2 * bw); 
 
    }, 
 
    drawScrollBox(){ 
 
     var displayHeight = this.height; 
 
     var scale = this.height/(this.lines.length * this.textHeight); 
 
     ctx.fillStyle = this.scrollBox.background; 
 
     ctx.fillRect(
 
      this.x + this.width - this.scrollBox.width, 
 
      this.y,this.scrollBox.width,this.height 
 
     ) 
 
     ctx.fillStyle = this.scrollBox.color; 
 
     ctx.fillRect(
 
      this.x + this.width - this.scrollBox.width, 
 
      this.y - (this.scrollY * scale), 
 
      this.scrollBox.width,this.height * scale 
 
     ) 
 
    }, 
 
    scroll(pos){ 
 
     this.cleanit();   
 
     this.scrollY = -pos; 
 
     if(this.scrollY > 0){ 
 
      this.scrollY = 0; 
 
     }else if(this.scrollY < -this.maxScroll){ 
 
      this.scrollY = -this.maxScroll ; 
 
     } 
 
    }, 
 
    render(){ 
 
     this.cleanit(); 
 
     ctx.font = this.fontStr; 
 
     ctx.textAlign = this.align; 
 
     this.drawBorder(); 
 
     ctx.save(); // need this to reset the clip area 
 

 
     ctx.fillStyle = this.background; 
 
     ctx.fillRect(this.x,this.y,this.width,this.height); 
 
     this.drawScrollBox(); 
 
     ctx.beginPath(); 
 
     ctx.rect(this.x,this.y,this.width-this.scrollBox.width,this.height); 
 
     ctx.clip();   
 
     // Important text does not like being place at fractions of a pixel 
 
     // make sure you round the y pos; 
 
     ctx.setTransform(1,0,0,1,this.x, Math.floor(this.y + this.scrollY)); 
 
     ctx.fillStyle = this.fontStyle; 
 

 
     for(var i = 0; i < this.lines.length; i ++){ 
 
      // Important text does not like being place at fractions of a pixel 
 
      // make sure you round the y pos; 
 
      ctx.fillText(this.lines[i],this.textPos,Math.floor(i * this.textHeight)); 
 
     } 
 
     ctx.restore(); // remove the clipping 
 
    } 
 
}  
 
function createScrollText(text, x, y, width, height, options = {}){ 
 
    return Object.assign({}, 
 
    textScrollBox,{ 
 
     text,x, y, width, height, 
 
     lines : [], 
 
    }, 
 
    options 
 
); 
 

 
} 
 
const text = "This is some random text added to the canvas via 2d API as a simple scroll box example at Stackoverflow. If you like any of the answers you find at stackoverflow and any of the other stack sites don't forget to upvote as a way to show your appreciation to all those that put in their free time to help others. Happy rendering " 
 
var scrollText = createScrollText(text, 10, 10, 200, 180); 
 
var scrollText1 = createScrollText(text, 220, 10, 270, 180); 
 
scrollText1.setOptions({ // set only the properties you want to change 
 
    fontStyle : "white", 
 
    scrollBox : { // if you add scrollbox you must put all property in for it 
 
     width : 5, 
 
     background : "#DDD", 
 
     color : "#555", 
 
    }, 
 
    border : { // if you add border you must put all property in for it 
 
     lineWidth : 4, 
 
     style : "black", 
 
     corner : "round", 
 
    }, 
 
    font : "Comic Sans MS", 
 
    fontSize : 36, 
 
    align :"center", 
 
}) 
 

 
function mainLoop(time){ 
 
    ctx.setTransform(1,0,0,1,0,0); 
 
    ctx.clearRect(0,0,canvas.width,canvas.height); 
 
    scrollText.scroll((Math.sin(time/3000) + 1) * scrollText.maxScroll * 0.5); 
 
    scrollText1.scroll((Math.sin(time/3462) + 1) * scrollText1.maxScroll * 0.5); 
 
    scrollText.render(); 
 
    scrollText1.render(); 
 
    requestAnimationFrame(mainLoop); 
 
} 
 
requestAnimationFrame(mainLoop);
canvas { 
 
border : 2px solid black; 
 
}
<canvas id="canvas" width=500 height=200></canvas>

+0

#Blindman67:この大きなデモと素晴らしいコード、感謝の男。マウスを動かすとマウスの動きにイベントを追加しようとします。 – Mimouni

関連する問題