2016-04-24 108 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