如何在paperjs中滚动大文本

时间:2015-03-15 14:45:30

标签: javascript canvas paperjs

我正在使用paper.js来创建(非交互式)显示。我有固定区域,我想在其中显示一些文字。当文本很大时,我想剪辑文本,以便只显示固定区域内的部分对用户可见。另外,在这种情况下,我想重复地从左到右滚动文本。

据我所知,在paperjs文件中,没有任何直接的方法来实现这一点(。 所以,我正在考虑做以下事情:

  • 确定文本是否大于容器框。找不到一个简单的方法来做到这一点。考虑有一个简单的启发式函数 - 它取决于文本中的字符数。
  • 剪切容器框内的文本。我还没想到,但似乎有可能。
  • 逐渐将锚点更改为左侧以创建滚动效果。再次确定要走多远,我们需要文本的大小 - 但可能需要再次依赖于启发式函数。

可能是即将发布的功能AreaText会让这更容易。如果有更好的方法可以在此期间告诉我。感谢。

如果在普通画布或其他js框架中有样本,请告诉我......

1 个答案:

答案 0 :(得分:2)

如果PaperJS适用于您的应用,但您需要滚动文本,则可以创建一个同时使用PaperJS画布和原生html5画布的混合应用。本机html5画布可以只滚动文本。

既然你要求创意......这是我做过一段时间的自动滚动文本脚本。

欢迎您使用代码作为滚动脚本的起点。它将句子包装成段落,然后在自动滚动的html画布上显示。

当您需要显示某些文本时,可以使用此滚动文本html5画布暂时覆盖PaperJS画布,并在显示文本时删除html5画布。使用html输入范围控件也很容易让用户控制滚动。

示例代码和演示:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var Paragraphs=( function(){
  function Paragraphs(x,y,maxwidth,fontsize,fontface){
    this.x=x;
    this.y=y;
    this.originalY=y;
    this.maxwidth=maxwidth;
    this.fontsize=fontsize;
    this.fontface=fontface;
    this.autoLineAdvance=true;
    this.writeCount=0;
    this.p=[];
    this.nextTime=0;
    this.duration=1000/60*1;
    this.viewheight=150;
    this.offsetY=0;
    this.canvas=document.createElement('canvas');
    this.ctx=this.canvas.getContext('2d');
    this.totalHeight=0;
  };
  Paragraphs.prototype.addParagraph=function(text){ this.p.push(text); }
  Paragraphs.prototype.autoscroll=function(viewportHeight){
    this.viewheight=ch;
    this.offsetY=ch;
    requestAnimationFrame(this.animatescroll.bind(this));                
  };
  Paragraphs.prototype.animatescroll=function(time){
    var that=this;
    if(this.offsetY>0){
      requestAnimationFrame(that.animatescroll.bind(that));
    }else{log('done');}
    if(time<this.nextTime){return;}
    this.nextTime=time+this.duration;
    ctx.clearRect(0,0,cw,ch);
    ctx.drawImage(this.canvas,this.x,this.offsetY);
    this.offsetY-=0.50;
  };
  Paragraphs.prototype.lineAdvance=function(){this.y+=this.fontsize*1.286*1.5};
  Paragraphs.prototype.drawOffCanvas=function(){
    var y=0;
    var lineCount=0;
    var lineHeight = this.fontsize*1.286;
    var lineAdvance=lineHeight*1.5;
    this.canvas.width=this.maxwidth;
    this.canvas.height=this.height();
    this.ctx.textBaseline='top';
    this.ctx.font = this.fontsize + "px " + this.fontface;
    for(var i=0;i<this.p.length;i++){
      var words=this.p[i].split(' ');
      var line = '';
      var space='';
      for (var n=0; n<words.length; n++) {
        var testLine = line + space + words[n];
        space=' ';
        if (this.ctx.measureText(testLine).width > this.maxwidth) {
          this.ctx.fillText(line, 1, y);
          line = words[n] + ' ';
          y += lineHeight;
          space='';
        } else {
          line = testLine;
        }
      }
      this.ctx.fillText(line, 1,y);
      y+=lineAdvance;
    }
  };
  Paragraphs.prototype.height=function(){
    ctx.save();
    ctx.textBaseline='top';
    ctx.font = this.fontsize + "px " + this.fontface;
    var lineHeight = this.fontsize*1.286;
    var writeCount=0;
    var height=lineHeight*(this.p.length-1)*0.50;
    var line,space;
    for(var i=0;i<this.p.length;i++){
      var words=this.p[i].split(' ');
      line=space='';
      if((writeCount++)>0){ height+=lineHeight; }
      for (var n=0; n<words.length; n++) {
        var testLine = line + space + words[n];
        space=' ';
        if (ctx.measureText(testLine).width > this.maxwidth) {
          line = words[n] + ' ';
          height+=lineHeight;
          space='';
        } else {
          line = testLine;
        }
      }
    }
    height+=lineHeight;
    ctx.restore();
    this.totalHeight=height;
    return(height);
  }
  return(Paragraphs);
})();


var d=new Paragraphs(35,20,200,14,'verdana');
d.addParagraph("I am using paper.js to create a (non-interactive) display. I have fixed area inside which I want to show some text. When the text is large, I want to clip the text so as to show only the part inside the fixed area is visible to the user. In addition, in that case, I want to scroll the text left-to-right repeatedly.");
d.addParagraph("Please let me know if there are samples in plain canvas or in another js framework ...");
d.drawOffCanvas();
d.autoscroll();
body{ background-color: ivory; padding:10px; }
canvas{border:1px solid red;}
<h4>Text scrolls in from the bottom<br>Be patient or click full page mode</h4>
<canvas id="canvas" width=300 height=300></canvas>