2016-04-24 92 views
2

创建我的画布,并得到var context = can.getContext('2d')后,我所有的油画作品是通过设置属性或调用方法上context.覆盖上下文。性能和功能

我创建了一个多显示器的截图工具,一台监视器上伟大的工作完成。但是现在,我正在处理多个显示器,因此不同的屏幕顶部/左侧和缩放。有时(比如在自定义DPI级别的Windows平台上)我必须扩展点。因此,我想通过一个覆盖函数来传递属性和方法的所有设置,以便在调用实际的context.BLAH之前,它将首先将坐标转换为当前屏幕坐标缩放和偏移的坐标。

我可以缩放上下文,但是这确实会导致视觉问题与抗锯齿。

这可能吗?

我尝试了过度的context.lineWidth和context.fillRect,但我得到了本地访问错误。

我想避免用它包裹:

function lineWidth(a) { 
doConvesionOnA(a) 
ctx.lineWidth = a; 
} 

,然后通过函数调用每次换行。但如果这是唯一的方式去包装它。我只是想先问问一下,然后再为每个房产和方法创建一个包裹,然后用我的包裹替换掉所有我的context.调用。

回答

2

这是可能的方法,但没有属性,因为它们通过验证和值是简单的拒绝如果不是一个有效的类型,即一个函数不能取代它(也不能更新内部设置如果它可以)。

我会建议,而不是使用包装对象。如果你想改变值方法

function MyContext(ctx) { 

    // Methods 

    this.moveTo = ctx.moveTo.bind(ctx); 
    this.lineTo = ctx.lineTo.bind(ctx); 
    // etc. 

    // Properties 

    Object.defineProperty(this, "lineWidth", { 
     get: function() {return ctx.lineWidth}, 
     set: function(value) { 
      // do something magic with value 
      ctx.lineWidth = value 
     } 
    }); 

    // etc. 
} 

this.moveTo = function(x, y) { 
    // alter here 
    ctx.moveTo(x, y); 
}; 

您还可以使用apply()这是灵活的,但不是通过速度较慢你可以把它与普通背景下兼容通过结合方法和包装性能在实际的论点中:

this.arc = function() { 
    ctx.arc.apply(ctx, arguments) 
}; 

它可能有点乏味,但让你完全控制传递到真实环境的东西。然后简单地创建对象的实例并将其用于2D上下文中:

var myCtx = new MyContext(ctx); 
myCtx.lineTo(100, 100); 
myCtx.lineWidth = 20; 
... 
+0

非常感谢您的参与!我会去这个方向。 – Noitidart

+0

非常感谢那篇关于'apply'的笔记,我不知道它是慢的。我会确保不这样做。 – Noitidart

+0

非常感谢,它的工作完美! https://github.com/Noitidart/NativeShot/blob/editor-revamp/resources/scripts/editor.js#L4423-L4544 – Noitidart

1

同意@ K3N的建议来包装上下文。

下面是一些代码,我抓住了我的CanvasRendingContext2D记录显示,你很快就能开始包裹CanvasRendingContext2D的:

function LoggedContext(canvas) { 
    var self = this; 
    this.canvas=canvas; 
    this.context=canvas.getContext('2d'); 
    this.imageURLs=[]; 
    this.fillStyles=[]; 
    this.logs=[]; 
    this.commands=[]; 
    this.funcs={}; 
    this.init(self); 
} 

LoggedContext.prototype.init方法,创建的get/set块各性能和互成镜像通过使用.apply将所有接收到的参数传递给“真实”上下文来处理上下文方法。

LoggedContext.prototype.init=function(self){ 

    // create get/sets for properties 
    var properties=['strokeStyle','lineWidth','font','globalAlpha', 
     'globalCompositeOperation','shadowColor','shadowBlur', 
     'shadowOffsetX','shadowOffsetY','lineCap','lineJoin', 
     'miterLimit','textAlign','textBaseline']; 

    for(var i=0;i<properties.length;i++){ 
     (function(i) { 
      Object.defineProperty(self, i, { 
       get: function() { 
        return this.context[i]; 
       }, 
       set: function (val) { 
        this.log(i,val,true); 
        this.context[i]=val; 
       } 
      }) 
     })(properties[i]); 
    } 

    // create mirror methods that pipe arguments to the real context 
    var methods = ['arc','beginPath','bezierCurveTo','clearRect','clip', 
     'closePath','fill','fillRect','fillText','lineTo','moveTo', 
     'quadraticCurveTo','rect','restore','rotate','save','scale','setTransform', 
     'stroke','strokeRect','strokeText','transform','translate','putImageData']; 

    for (var i=0;i<methods.length;i++){ 
     var m = methods[i]; 
     this[m] = (function(m){ 
      return function() { 
       this.context[m].apply(this.context, arguments); 
       this.log(m,arguments); 
       return(this); 
     };}(m)); 
    } 

    // mirror methods that have return values 
    var returnMethods = ['measureText','getImageData','toDataURL', 
     'isPointInPath','isPointInStroke','createImageData']; 

    for (var i=0;i<returnMethods.length;i++){ 
     var m = returnMethods[i]; 
     this[m] = (function(m){ 
      return function() { 
       return(this.context[m].apply(this.context, arguments)); 
     };}(m)); 
    } 

    // In this example code ... 
    // These Properties & Methods requiring special handling have 
    // been removed for brevity & clarity 
    // 
    // .fillStyle 
    // .strokeStyle 
    // .drawImage 
    // .createLinearGradient 
    // .createRadialGradient 
    // .createPattern 


} // end init() 

所有属性get/set和所有的方法调用都是通过LoggedContext.prototype.log方法引导。

你的目的,你既可以使您的调整了get/set块或方便地进行中.log方法的调整,因为一切都是通过.log方法管道。

LoggedContext.prototype.log=function(command,Args,isProperty){ 
    var commandIndex=this.commands.indexOf(command); 
    if(commandIndex<0){ 
     this.commands.push(command); 
     commandIndex=this.commands.length-1 
    } 
    if(isProperty){ 
     this.logs.push([commandIndex,Args]); 
    }else{ 
     this.logs.push([commandIndex,Array.prototype.slice.call(Args)]); 
    } 
} 
+0

非常感谢您帮助我开始使用代码marke!当你们都推荐时,我会做包装的事情。 – Noitidart

+1

非常感谢这真的帮助了我一吨! https://github.com/Noitidart/NativeShot/blob/editor-revamp/resources/scripts/editor.js#L4423-L4544 – Noitidart