2017-06-11 4 views
0

Ich habe einen großen Text in einer Leinwand einfügen.Erstellen Sie einen scrollbaren Text in Canvas

zuerst wickle ich den Text, und jetzt versuche ich es in der Leinwand scrollbar machen.

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); 

danke für Ihre Hilfe.

Antwort

1

Die Leinwand ist nur ein Pixelspeicher. Es erinnert sich nicht, was gezeichnet wird, außer für die Pixel. Um ein Bildlauffeld zu erstellen, müssen Sie jedes Mal das gesamte Bildlauffeld rendern, wenn Sie es bewegen.

Mit dem Kontext können Sie einen Clipbereich festlegen. Sie verwenden das, um sicherzustellen, dass Text außerhalb der Grenzen nicht angezeigt wird.

Verwenden Sie die Option ctx.setTransform t, um die Bildlaufposition für das Rendern festzulegen. Wenn Sie nach oben scrollen, muss die Bildlaufposition ins Negative gehen.

Demo ist ein sehr einfaches Beispiel für eine Textlaufleiste. Es hat keine Optimierungen und die Textanpassung hat keine echte Intelligenz.

Siehe Code für Details, es ist ziemlich einfach Code so nicht so viele Kommentare. Fragen Sie in den Kommentaren, wenn Sie Fragen haben.

Es gibt keine Maus oder Benutzerinteraktion, die ich Ihnen überlassen.

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: Das ist eine große Demonstration und ein großer Code, Menschen danken. Ich werde versuchen, Ereignisse auf der Maus nach unten und bei der Mausbewegung hinzuzufügen. – Mimouni

Verwandte Themen