canvas 判断点是否在多边形内部
射线法判断点是否在多边形内部
/** * @description 射线法判断点是否在多边形内部 * @param {Object} p 待判断的点,格式:{ x: X坐标, y: Y坐标 } * @param {Array} poly 多边形顶点,数组成员的格式同 p * @return {String} 点 p 和多边形 poly 的几何关系 */ function rayCasting(p, poly) { var px = p.x, py = p.y, flag = false for(var i = 0, l = poly.length, j = l - 1; i < l; j = i, i++) { var sx = poly[i].x, sy = poly[i].y, tx = poly[j].x, ty = poly[j].y // 点与多边形顶点重合 if((sx === px && sy === py) || (tx === px && ty === py)) { return 'on' } // 判断线段两端点是否在射线两侧 if((sy < py && ty >= py) || (sy >= py && ty < py)) { // 线段上与射线 Y 坐标相同的点的 X 坐标 var x = sx + (py - sy) * (tx - sx) / (ty - sy) // 点在多边形的边上 if(x === px) { return 'on' } // 射线穿过多边形的边界 if(x > px) { flag = !flag } } } // 射线穿过多边形边界的次数为奇数时点在多边形内 return flag ? 'in' : 'out' }
回转数法实现 判断点是否在多边形内部
/** * @description 回转数法判断点是否在多边形内部 * @param {Object} p 待判断的点,格式:{ x: X坐标, y: Y坐标 } * @param {Array} poly 多边形顶点,数组成员的格式同 p * @return {String} 点 p 和多边形 poly 的几何关系 */ function windingNumber(p, poly) { var px = p.x, py = p.y, sum = 0 for(var i = 0, l = poly.length, j = l - 1; i < l; j = i, i++) { var sx = poly[i].x, sy = poly[i].y, tx = poly[j].x, ty = poly[j].y // 点与多边形顶点重合或在多边形的边上 if((sx - px) * (px - tx) >= 0 && (sy - py) * (py - ty) >= 0 && (px - sx) * (ty - sy) === (py - sy) * (tx - sx)) { return 'on' } // 点与相邻顶点连线的夹角 var angle = Math.atan2(sy - py, sx - px) - Math.atan2(ty - py, tx - px) // 确保夹角不超出取值范围(-π 到 π) if(angle >= Math.PI) { angle = angle - Math.PI * 2 } else if(angle <= -Math.PI) { angle = angle + Math.PI * 2 } sum += angle } // 计算回转数并判断点和多边形的几何关系 return Math.round(sum / Math.PI) === 0 ? 'out' : 'in' }
参考:
http://www.html-js.com/article/1538
isPointInPath()方法 定义与用法: isPointInPath()方法返回true,如果给定的点的坐标位于路径之内的话(包括路径的边),否则返回 false。 语法: context.isPointInPath(x,y);//其中x,y分别是给定点的横、纵坐标 isPointInStroke() 是 Canvas 2D API 用于检测某点是否在路径的描边线上的方法。返回值是一个布尔值,当这个点在路径的描边线上,则返回true,否则返回false。
结合 isPointInPath,然后判断 点与边界重合,这样兼容点在线上的点击事件;
canvas Retina 屏幕优化
/** * HiDPI Canvas Polyfill (1.0.9) * * Author: Jonathan D. Johnson (http://jondavidjohn.com) * Homepage: https://github.com/jondavidjohn/hidpi-canvas-polyfill * Issue Tracker: https://github.com/jondavidjohn/hidpi-canvas-polyfill/issues * License: Apache 2.0 */ ;(function(prototype) { var pixelRatio = (function(context) { var backingStore = context.backingStorePixelRatio || context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio || context.msBackingStorePixelRatio || context.oBackingStorePixelRatio || context.backingStorePixelRatio || 1; return (window.devicePixelRatio || 1) / backingStore; })(prototype), forEach = function(obj, func) { for (var p in obj) { if (obj.hasOwnProperty(p)) { func(obj[p], p); } } }, ratioArgs = { 'fillRect': 'all', 'clearRect': 'all', 'strokeRect': 'all', 'moveTo': 'all', 'lineTo': 'all', 'arc': [0,1,2], 'arcTo': 'all', 'bezierCurveTo': 'all', 'isPointinPath': 'all', 'isPointinStroke': 'all', 'quadraticCurveTo': 'all', 'rect': 'all', 'translate': 'all', 'createRadialGradient': 'all', 'createLinearGradient': 'all' }; if (pixelRatio === 1) return; forEach(ratioArgs, function(value, key) { prototype[key] = (function(_super) { return function() { var i, len, args = Array.prototype.slice.call(arguments); if (value === 'all') { args = args.map(function(a) { return a * pixelRatio; }); } else if (Array.isArray(value)) { for (i = 0, len = value.length; i < len; i++) { args[value[i]] *= pixelRatio; } } return _super.apply(this, args); }; })(prototype[key]); }); // Stroke lineWidth adjustment prototype.stroke = (function(_super) { return function() { this.lineWidth *= pixelRatio; _super.apply(this, arguments); this.lineWidth /= pixelRatio; }; })(prototype.stroke); // Text // prototype.fillText = (function(_super) { return function() { var args = Array.prototype.slice.call(arguments); args[1] *= pixelRatio; // x args[2] *= pixelRatio; // y this.font = this.font.replace( /(d+)(px|em|rem|pt)/g, function(w, m, u) { return (m * pixelRatio) + u; } ); _super.apply(this, args); this.font = this.font.replace( /(d+)(px|em|rem|pt)/g, function(w, m, u) { return (m / pixelRatio) + u; } ); }; })(prototype.fillText); prototype.strokeText = (function(_super) { return function() { var args = Array.prototype.slice.call(arguments); args[1] *= pixelRatio; // x args[2] *= pixelRatio; // y this.font = this.font.replace( /(d+)(px|em|rem|pt)/g, function(w, m, u) { return (m * pixelRatio) + u; } ); _super.apply(this, args); this.font = this.font.replace( /(d+)(px|em|rem|pt)/g, function(w, m, u) { return (m / pixelRatio) + u; } ); }; })(prototype.strokeText); })(CanvasRenderingContext2D.prototype); ;(function(prototype) { prototype.getContext = (function(_super) { return function(type) { var backingStore, ratio, context = _super.call(this, type); if (type === '2d') { backingStore = context.backingStorePixelRatio || context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio || context.msBackingStorePixelRatio || context.oBackingStorePixelRatio || context.backingStorePixelRatio || 1; ratio = (window.devicePixelRatio || 1) / backingStore; if (ratio > 1) { this.style.height = this.height + 'px'; this.style.width = this.width + 'px'; this.width *= ratio; this.height *= ratio; } } return context; }; })(prototype.getContext); })(HTMLCanvasElement.prototype);
jcanvascript.js类库 备份
/*! * jCanvaScript JavaScript Library v 1.5.18 * http://jcscript.com/ * * Copyright 2012, Alexander Savin * Dual licensed under the MIT or GPL Version 2 licenses. */ (function (window, undefined) { var canvases = [], m = Math, m_pi = m.PI, pi2 = m_pi * 2, lastCanvas = 0, lastLayer = 0, underMouse = false, underMouseLayer = false, regHasLetters = /[A-z]+?/, regNumsWithMeasure = /d.ww/, FireFox = window.navigator.userAgent.match(/Firefox/w+.w+/i), radian = 180 / m_pi, m_max = m.max, m_min = m.min, m_cos = m.cos, m_sin = m.sin, m_floor = m.floor, m_round = m.round, m_abs = m.abs, m_pow = m.pow, m_sqrt = m.sqrt, fps = 1000 / 60, requestAnimFrame = (function () { return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback, element) { return setTimeout(callback, fps); } })(), cancelRequestAnimFrame = (function () { return window.cancelAnimationFrame || window.webkitCancelRequestAnimationFrame || window.mozCancelRequestAnimationFrame || window.oCancelRequestAnimationFrame || window.msCancelRequestAnimationFrame || clearTimeout })(); if (FireFox != "" && FireFox !== null) var FireFox_lt_7 = (parseInt(FireFox[0].split(/[ /.]/i)[1]) < 7); function findById(i, j, stroke) { var objs = canvases[i].layers[j].objs, grdntsnptrns = canvases[i].layers[j].grdntsnptrns, objsLength = objs.length, grdntsnptrnsLength = grdntsnptrns.length; stroke = stroke.slice(1); for (var k = 0; k < objsLength; k++) if (objs[k].optns.id == stroke)return objs[k]; for (k = 0; k < grdntsnptrnsLength; k++) if (grdntsnptrns[k].optns.id == stroke)return grdntsnptrns[k]; return false; } function findByName(i, j, myGroup, stroke) { var objs = canvases[i].layers[j].objs, grdntsnptrns = canvases[i].layers[j].grdntsnptrns, strokes = stroke.slice(1).split('.'); findByNames(myGroup, strokes, objs); findByNames(myGroup, strokes, grdntsnptrns); return myGroup; function findByNames(myGroup, strokes, objs){ var objsLength = objs.length, names, l, k, m; for (k = 0; k < objsLength; k++) { names = objs[k]._name.split(' '); if(strokes.length > names.length){ continue; } var strokesClone = strokes.concat(); for(l = 0; l < names.length; l++){ for(m = 0; m < strokesClone.length; m++){ if (names[l] === strokesClone[m]) { strokesClone.splice(m, 1); m--; continue; } } if(!strokesClone.length){ myGroup.elements.push(objs[k]); break; } } } } } function findByCanvasAndLayer(i, j, myGroup) { var objs = canvases[i].layers[j].objs, grdntsnptrns = canvases[i].layers[j].grdntsnptrns, objsLength = objs.length, grdntsnptrnsLength = grdntsnptrns.length; for (var k = 0; k < objsLength; k++) myGroup.elements.push(objs[k]); for (k = 0; k < grdntsnptrnsLength; k++) myGroup.elements.push(grdntsnptrns[k]); return myGroup; } var jCanvaScript = function (stroke, map) { if (stroke === undefined)return this; if (typeof stroke == 'object') { map = stroke; stroke = undefined; } var canvasNumber = -1, layerNumber = -1, limitC = canvases.length, myGroup = group(), i, j, canvas, layer, layers, element, limitL; if (map === undefined) { if (stroke.charAt(0) === '#') { for (i = 0; i < limitC; i++) { limitL = canvases[i].layers.length; for (j = 0; j < limitL; j++) { element = findById(i, j, stroke); if (element)return element; } } } if (stroke.charAt(0) === '.') { for (i = 0; i < limitC; i++) { limitL = canvases[i].layers.length; for (j = 0; j < limitL; j++) myGroup = findByName(i, j, myGroup, stroke); } } } else { if (map.canvas !== undefined) { for (i = 0; i < limitC; i++) if (canvases[i].optns.id == map.canvas) { canvasNumber = i; canvas = canvases[i]; break; } } if (map.layer !== undefined) { if (canvasNumber != -1) { limitL = canvas.layers.length; for (i = 0; i < limitL; i++) if (canvas.layers[i].optns.id == map.layer) { layerNumber = i; layer = canvas.layers[i]; break; } } else { for (i = 0; i < limitC; i++) { layers = canvases[i].layers; limitL = layers.length; for (j = 0; j < limitL; j++) { if (layers[j].optns.id == map.layer) { canvasNumber = i; layerNumber = j; canvas = canvases[i] layer = canvas.layers[j]; break; } } if (layer > -1)break; } } } if (layerNumber < 0 && canvasNumber < 0)return group(); if (layerNumber < 0) { layers = canvas.layers; limitL = layers.length; if (stroke === undefined) { for (j = 0; j < limitL; j++) myGroup = findByCanvasAndLayer(canvasNumber, j, myGroup); } else if (stroke.charAt(0) === '#') { for (j = 0; j < limitL; j++) { element = findById(canvasNumber, j, stroke); if (element)return element; } } else if (stroke.charAt(0) === '.') { for (j = 0; j < limitL; j++) myGroup = findByName(canvasNumber, j, myGroup, stroke); } } else { if (stroke === undefined) { myGroup = findByCanvasAndLayer(canvasNumber, layerNumber, myGroup); } if (stroke.charAt(0) === '#') { return findById(canvasNumber, layerNumber, stroke); } if (stroke.charAt(0) === '.') { myGroup = findByName(canvasNumber, layerNumber, myGroup, stroke) } } } if (map !== undefined) if (map.attrs !== undefined || map.fns !== undefined) return myGroup.find(map); if (myGroup.elements.length)return myGroup; return group(); } function changeMatrix(object) { var optns=object.optns; object.matrix(multiplyM(multiplyM(multiplyM(optns.transformMatrix,optns.translateMatrix),optns.scaleMatrix),optns.rotateMatrix)); redraw(object); } function checkDefaults(check,def) { for(var key in def) { if(check[key]===undefined)check[key]=def[key]; } return check; } function redraw(object) { objectCanvas(object).optns.redraw=1; } function animating(canvasOptns) { var timeDiff=canvasOptns.timeDiff, progress=1; for(var q=0;q<this.animateQueue.length;q++) { var queue=this.animateQueue[q], duration=queue['duration'], easing=queue['easing'], step=queue.step, onstep=queue['onstep'], easingIn=easing['type']=='in' || (easing['type']=='inOut' && progress<0.5), easingOut=easing['type']=='out' || (easing['type']=='inOut' && progress>0.5); queue['step']+=timeDiff; progress=step/duration; for(var key in queue) { if(this[key]!==undefined && queue[key]) { var property=queue[key], to=property['to'], from=property['from']; animateTransforms(key,this,queue); if(easingIn)this[key]=(to-from)*animateFunctions[easing['fn']](progress,easing)+from; if(easingOut)this[key]=(to-from)*(1-animateFunctions[easing['fn']](1-progress,easing))+from; if(onstep)onstep.fn.call(this,onstep); if(step>=duration) { this[key]=to; animateTransforms(key,this,queue); queue[key]=false; queue.animateKeyCount--; if(!queue.animateKeyCount) { if(queue.animateFn)queue.animateFn.apply(this); this.animateQueue.splice(q,1); q--; } } } } } if (this.animateQueue.length)redraw(this); else this.optns.animated=false; return this; } function animateTransforms(key,object,queue) { var val=object[key]; var prev=queue[key]['prev']; switch(key) { case '_rotateAngle': object.rotate(val-prev,object._rotateX,object._rotateY); break; case '_translateX': object.translate(val-prev,0); break; case '_translateY': object.translate(0,val-prev); break; case '_translateToX': object.translateTo(val,undefined); break; case '_translateToY': object.translateTo(undefined,val); break; case '_scaleX': if(!prev)prev=1; object.scale(val/prev,1); break; case '_scaleY': if(!prev)prev=1; object.scale(1,val/prev); break; default: return; } queue[key]['prev']=val; } function keyEvent(e,key,optns) { e=e||window.event; optns[key].event=e; optns[key].code=e.charCode||e.keyCode; optns[key].val=true; optns.redraw=1; } function mouseEvent(e,key,optns) { if(!optns[key].val)return; e=e||window.event; var point= { pageX:e.pageX||e.clientX, pageY:e.pageY||e.clientY }; optns[key].event=e; optns[key].x=point.pageX - optns.x; optns[key].y=point.pageY - optns.y; optns.redraw=1; } function setMouseEvent(fn,eventName) { if(fn===undefined)this['on'+eventName](); else this['on'+eventName] = fn; if(eventName=='mouseover'||eventName=='mouseout')eventName='mousemove'; objectCanvas(this).optns[eventName].val=true; return this; } function setKeyEvent(fn,eventName) { if(fn===undefined)this[eventName](); else this[eventName] = fn; return this; } var animateFunctions={ linear:function(progress,params){ return progress; }, exp:function(progress,params){ var n=params.n||2; return m_pow(progress,n); }, circ:function(progress,params){ return 1 - m_sqrt(1-progress*progress); }, sine:function(progress,params){ return 1 - m_sin((1 - progress) * m_pi/2); }, back:function(progress,params){ var n=params.n||2; var x=params.x||1.5; return m_pow(progress, n) * ((x + 1) * progress - x); }, elastic:function(progress,params){ var n=params.n||2; var m=params.m||20; var k=params.k||3; var x=params.x||1.5; return m_pow(n,10 * (progress - 1)) * m_cos(m * progress * m_pi * x / k); }, bounce:function(progress,params) { var n=params.n||4; var b=params.b||0.25; var sum = [1]; for(var i=1; i<n; i++) sum[i] = sum[i-1] + m_pow(b, i/2); var x = 2*sum[n-1]-1; for(i=0; i<n; i++) { if(x*progress >= (i>0 ? 2*sum[i-1]-1 : 0) && x*progress <= 2*sum[i]-1) return m_pow(x*(progress-(2*sum[i]-1-m_pow(b, i/2))/x), 2)+1-m_pow(b, i); } return 1; } }, imageDataFilters={ color:{fn:function(width,height,matrix,type){ var old,i,j; matrix=matrix[type]; for(i=0;i<width;i++) for(j=0;j<height;j++) { old=this.getPixel(i,j); old[matrix[0]]=old[matrix[0]]*2-old[matrix[1]]-old[matrix[2]]; old[matrix[1]]=0; old[matrix[2]]=0; old[matrix[0]]=old[matrix[0]]>255?255:old[matrix[0]]; this.setPixel(i,j,old); } },matrix: { red:[0,1,2], green:[1,0,2], blue:[2,0,1] }}, linear:{fn:function(width,height,matrix,type){ var newMatrix=[],old,i,j,k,m,n; matrix=matrix[type]; m=matrix.length; n=matrix[0].length; for(i=0;i<width;i++) { newMatrix[i]=[]; for(j=0;j<height;j++) { newMatrix[i][j]=[0,0,0,1]; for(m=0;m<3;m++) for(n=0;n<3;n++) { old=this.getPixel(i-parseInt(m/2),j-parseInt(n/2)); for(k=0;k<3;k++) { newMatrix[i][j][k]+=old[k]*matrix[m][n]; } } } } for(i=0;i<width;i++) { for(j=0;j<height;j++) this.setPixel(i,j,newMatrix[i][j]); } }, matrix:{ sharp:[[-0.375,-0.375,-0.375],[-0.375,4,-0.375],[-0.375,-0.375,-0.375]], blur:[[0.111,0.111,0.111],[0.111,0.111,0.111],[0.111,0.111,0.111]] } } } function multiplyM(m1,m2) { return [[(m1[0][0]*m2[0][0]+m1[0][1]*m2[1][0]),(m1[0][0]*m2[0][1]+m1[0][1]*m2[1][1]),(m1[0][0]*m2[0][2]+m1[0][1]*m2[1][2]+m1[0][2])],[(m1[1][0]*m2[0][0]+m1[1][1]*m2[1][0]),(m1[1][0]*m2[0][1]+m1[1][1]*m2[1][1]),(m1[1][0]*m2[0][2]+m1[1][1]*m2[1][2]+m1[1][2])]]; } function multiplyPointM(x,y,m) { return { x:(x*m[0][0]+y*m[0][1]+m[0][2]), y:(x*m[1][0]+y*m[1][1]+m[1][2]) } } function transformPoint(x,y,m) { return{ x:(x*m[1][1]-y*m[0][1]+m[0][1]*m[1][2]-m[1][1]*m[0][2])/(m[0][0]*m[1][1]-m[1][0]*m[0][1]), y:(-x*m[1][0]+y*m[0][0]-m[0][0]*m[1][2]+m[1][0]*m[0][2])/(m[0][0]*m[1][1]-m[1][0]*m[0][1]) } } function getRect(object,rect,type) { if(type=='poor')return rect; var min={x:rect.x,y:rect.y},max={x:rect.x+rect.width,y:rect.y+rect.height}, m=multiplyM(object.matrix(),objectLayer(object).matrix()), lt=multiplyPointM(min.x,min.y,m), rt=multiplyPointM(max.x,min.y,m), lb=multiplyPointM(min.x,max.y,m), rb=multiplyPointM(max.x,max.y,m), coords=[[lt.x,lt.y],[rt.x,rt.y],[lb.x,lb.y],[rb.x,rb.y]]; if(type=='coords')return coords; var minX, minY, maxX=minX=lt.x, maxY=minY=lt.y; for(var i=0;i<4;i++) { if(maxX<coords[i][0])maxX=coords[i][0]; if(maxY<coords[i][1])maxY=coords[i][1]; if(minX>coords[i][0])minX=coords[i][0]; if(minY>coords[i][1])minY=coords[i][1]; } return {x:minX,y:minY,maxX-minX,height:maxY-minY}; } function getCenter(object,point,type) { if(type=='poor')return point; return multiplyPointM(point.x,point.y,multiplyM(object.matrix(),objectLayer(object).matrix())); } function parseColor(color) { var colorKeeper={ color:{ val:color, notColor:undefined }, r:0, g:0, b:0, a:1}; if(color.id!==undefined) { colorKeeper.color.notColor={ level:color._level, canvas:color.optns.canvas.number, layer:color.optns.layer.number } return colorKeeper; } if(color.r!==undefined) { colorKeeper=checkDefaults(color,{r:0,g:0,b:0,a:1}); colorKeeper.color={ val:'rgba('+colorKeeper.r+','+colorKeeper.g+','+colorKeeper.b+','+colorKeeper.a+')', notColor:undefined } return colorKeeper; } if(color.charAt(0)=='#') { if (color.length > 4) { colorKeeper.r = parseInt(color.substr(1, 2), 16); colorKeeper.g = parseInt(color.substr(3, 2), 16); colorKeeper.b = parseInt(color.substr(5, 2), 16); } else { var r = color.charAt(1), g = color.charAt(2), b = color.charAt(3); colorKeeper.r = parseInt(r + r, 16); colorKeeper.g = parseInt(g + g, 16); colorKeeper.b = parseInt(b + b, 16); } } else { var arr=color.split(','); if(arr.length==4) { var colorR = arr[0].split('('); var alpha = arr[3].split(')'); colorKeeper.r=parseInt(colorR[1]); colorKeeper.g=parseInt(arr[1]); colorKeeper.b=parseInt(arr[2]); colorKeeper.a=parseFloat(alpha[0]); } if(arr.length==3) { colorR = arr[0].split('('); var colorB = arr[2].split(')'); colorKeeper.r=parseInt(colorR[1]); colorKeeper.g=parseInt(arr[1]); colorKeeper.b=parseInt(colorB[0]); } } colorKeeper.color.notColor = undefined; return colorKeeper; } function getOffset(elem) { if (elem.getBoundingClientRect) { return getOffsetRect(elem) } else { return getOffsetSum(elem) } } function getOffsetSum(elem) { var top=0, left=0 while(elem) { top = top + parseInt(elem.offsetTop) left = left + parseInt(elem.offsetLeft) elem = elem.offsetParent } return { top: top, left: left } } function getOffsetRect(elem) { var box = elem.getBoundingClientRect() var body = document.body||{}; var docElem = document.documentElement var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft var clientTop = docElem.clientTop || body.clientTop || 0 var clientLeft = docElem.clientLeft || body.clientLeft || 0 var top = box.top + scrollTop - clientTop var left = box.left + scrollLeft - clientLeft return { top: m_round(top), left: m_round(left) } } function checkEvents(object,optns) { checkMouseEvents(object,optns); checkKeyboardEvents(object,optns); } function checkKeyboardEvents(object,optns) { if(!object.optns.focused)return; if(optns.keyDown.val!=false)if(typeof object.onkeydown=='function')object.onkeydown(optns.keyDown); if(optns.keyUp.val!=false)if(typeof object.onkeyup=='function')object.onkeyup(optns.keyUp); if(optns.keyPress.val!=false)if(typeof object.onkeypress=='function')object.onkeypress(optns.keyPress); } function isPointInPath(object,x,y) { var point={}; var canvas=objectCanvas(object); var ctx=canvas.optns.ctx; var layer=canvas.layers[object.optns.layer.number]; point.x=x; point.y=y; if(FireFox_lt_7) { point=transformPoint(x,y,layer.matrix()); point=transformPoint(point.x,point.y,object.matrix()); } if(ctx.isPointInPath===undefined || object._img!==undefined || object._imgData!==undefined || object._proto=='text') { var rectangle=object.getRect('poor'); var poorPoint=transformPoint(x,y,multiplyM(object.matrix(),layer.matrix())); if(rectangle.x<=poorPoint.x && rectangle.y<=poorPoint.y && (rectangle.x+rectangle.width)>=poorPoint.x && (rectangle.y+rectangle.height)>=poorPoint.y)return point; } else { if(ctx.isPointInPath(point.x,point.y)){ return point; } } return false } function checkMouseEvents(object,optns) { var point=false, mm=optns.mousemove, md=optns.mousedown, mu=optns.mouseup, c=optns.click, dc=optns.dblclick, x=mm.x||md.x||mu.x||dc.x||c.x, y=mm.y||md.y||mu.y||dc.y||c.y; if(x!=false) { point=isPointInPath(object,x,y); } if(point) { if(mm.x!=false) mm.object=object; if(md.x!=false) md.objects[md.objects.length]=object; if(c.x!=false) c.objects[c.objects.length]=object; if(dc.x!=false) dc.objects[dc.objects.length]=object; if(mu.x!=false) mu.objects[mu.objects.length]=object; optns.point=point; } } function objectLayer(object) { return objectCanvas(object).layers[object.optns.layer.number]; } function objectCanvas(object) { return canvases[object.optns.canvas.number]; } function layer(idLayer,object,array) { redraw(object); var objectCanvas=object.optns.canvas; var objectLayer=object.optns.layer; if (idLayer===undefined)return objectLayer.id; if(objectLayer.id==idLayer)return object; var oldIndex={ i:objectCanvas.number, j:objectLayer.number }; objectLayer.id=idLayer; var newLayer=jCanvaScript.layer(idLayer); var newIndex={ i:newLayer.optns.canvas.number, j:newLayer.optns.number }; var oldArray=canvases[oldIndex.i].layers[oldIndex.j][array],newArray=canvases[newIndex.i].layers[newIndex.j][array]; oldArray.splice(object.optns.number,1); object._level=object.optns.number=newArray.length; newArray[object._level]=object; objectLayer.number=newIndex.j; objectCanvas.number=newIndex.i; objectCanvas.id=newLayer.optns.canvas.id; redraw(object); return object; } function take(f,s) { for(var key in s) { switch(typeof s[key]) { case 'function': if(key.substr(0,2)=='on')break; if(f[key]===undefined)f[key]=s[key]; break; case 'object': if(key=='optns' || key=='animateQueue')break; if(key=='objs' || key=='grdntsnptrns') { for(var i in s[key]) { if(s[key].hasOwnProperty(i)) s[key][i].clone().layer(f.optns.id); } break; } if(!s[key] || key==='ctx')continue; f[key]=typeof s[key].pop === 'function' ? []:{}; take(f[key],s[key]); break; default: if(key=='_level')break; f[key]=s[key]; } } } function canvas(idCanvas,object,array) { redraw(object); var objectCanvas=object.optns.canvas; var objectLayer=object.optns.layer; if(idCanvas===undefined)return canvases[objectCanvas.number].optns.id; if(canvases[objectCanvas.number].optns.id==idCanvas)return object; var oldIndex={ i:objectCanvas.number, j:objectLayer.number }; jCanvaScript.canvas(idCanvas); for(var i=0;i<canvases.length;i++) { var canvasItem=canvases[i]; if(canvasItem.optns.id==idCanvas) { var oldArray=canvases[oldIndex.i].layers[oldIndex.j][array],newArray=canvasItem.layers[0][array]; oldArray.splice(object.optns.number,1); normalizeLevels(oldArray); object._level=object.optns.number=newArray.length; newArray[object._level]=object; objectLayer.number=0; objectCanvas.number=i; objectCanvas.id=canvasItem.optns.id; objectLayer.id=canvasItem.layers[0].optns.id; } } redraw(object); return object; } function normalizeLevels(array) { for(var i=0;i<array.length;i++) { array[i].optns.number=i; } } function setLayerAndCanvasToArray(array,newLayerId,newLayerNumber,newCanvasId,newCanvasNumber) { var limit=array.length, optns,canvas,layer; for(var i=0;i<limit;i++) { optns=array[i].optns; canvas=optns.canvas; layer=optns.layer; canvas.id=newCanvasId; canvas.number=newCanvasNumber; layer.id=newLayerId; layer.number=newLayerNumber; } } function levelChanger(array) { array.sort(function(a,b){ if(a._level>b._level)return 1; if(a._level<b._level)return -1; return 0; }); normalizeLevels(array); return array.length; } function objDeleter(array) { var isAnyObjectDeleted; do{ isAnyObjectDeleted=false; for(var i=0;i<array.length;i++) { if(array[i].optns.deleted) { array.splice(i,1); isAnyObjectDeleted=true; } } }while(isAnyObjectDeleted); normalizeLevels(array); return array.length; } var proto={}; proto.object=function() { this.getCenter=function(type){ var rect=this.getRect('poor'), point = { x:(rect.x*2+rect.width)/2, y:(rect.y*2+rect.height)/2 }; return getCenter(this,point,type); } this.position=function(){ return multiplyPointM(this._x,this._y,multiplyM(this.matrix(),objectLayer(this).matrix())); } this.buffer=function(doBuffering){ var bufOptns=this.optns.buffer; if(doBuffering===undefined) if(bufOptns.val)return bufOptns.cnv; else return false; if(bufOptns.val===doBuffering)return this; if(doBuffering) { var cnv=bufOptns.cnv=document.createElement('canvas'), ctx=bufOptns.ctx=cnv.getContext('2d'), rect=bufOptns.rect=this.getRect(), oldM=this.transform(); cnv.setAttribute('width',rect.width); cnv.setAttribute('height',rect.height); bufOptns.x=this._x; bufOptns.y=this._y; bufOptns.dx=this._transformdx; bufOptns.dy=this._transformdy; this._x=this._y=0; this.transform(1, 0, 0, 1, -rect.x+bufOptns.dx, -rect.y+bufOptns.dy,true); this.setOptns(ctx); take(bufOptns.optns={},objectCanvas(this).optns); bufOptns.optns.ctx=ctx; this.draw(bufOptns.optns); this._x=bufOptns.x; this._y=bufOptns.y; this.transform(oldM[0][0], oldM[1][0], oldM[0][1], oldM[1][1], rect.x, rect.y,true); bufOptns.val=true; } else { this.translate(-bufOptns.rect.x+bufOptns.dx,-bufOptns.rect.y+bufOptns.dy); this.optns.buffer={val:false}; } return this; } this.clone=function(params) { var clone=new proto[this._proto]; proto[this._proto].prototype.base.call(clone); take(clone,this); clone.layer(objectLayer(this).optns.id); take(clone.optns.transformMatrix,this.optns.transformMatrix); take(clone.optns.translateMatrix,this.optns.translateMatrix); take(clone.optns.scaleMatrix,this.optns.scaleMatrix); take(clone.optns.rotateMatrix,this.optns.rotateMatrix); if(params===undefined) return clone; return clone.animate(params); } this.shadow= function(options) { for(var key in options) switch (key) { case 'x': this._shadowX=options.x; break; case 'y': this._shadowY=options.y; break; case 'blur': this._shadowBlur=options.blur; break; case 'color': var colorKeeper = parseColor(options.color); this._shadowColor = options.color.val; this._shadowColorR = colorKeeper.r; this._shadowColorG = colorKeeper.g; this._shadowColorB = colorKeeper.b; this._shadowColorA = colorKeeper.a; break; } redraw(this); return this; } this.setOptns=function(ctx) { ctx.globalAlpha = this._opacity; ctx.shadowOffsetX = this._shadowX; ctx.shadowOffsetY = this._shadowY; ctx.shadowBlur = this._shadowBlur; ctx.globalCompositeOperation=this._composite; var rInt = parseInt(this._shadowColorR), gInt = parseInt(this._shadowColorG), bInt = parseInt(this._shadowColorB), aInt = parseInt(this._shadowColorA * 100) / 100; if (this._shadowColorRPrev !== rInt || this._shadowColorGPrev !== gInt || this._shadowColorBPrev !== bInt || this._shadowColorAPrev !== aInt) { ctx.shadowColor = this._shadowColor = 'rgba(' + rInt + ', ' + gInt + ', ' + bInt + ', ' + aInt+ ')'; this._shadowColorRPrev = rInt; this._shadowColorGPrev = gInt; this._shadowColorBPrev = bInt; this._shadowColorAPrev = aInt; } else { ctx.shadowColor = this._shadowColor; } ctx.transform(this._transform11,this._transform12,this._transform21,this._transform22,this._transformdx,this._transformdy); return this; } this.up=function(n) { if(n === undefined)n=1; if(n=='top')this.level(n); else { var next=objectLayer(this).objs[this.optns.number+n]; if(next!==undefined) { n=next._level+1-this._level; } this.level(this._level+n); } return this; } this.down=function(n) { if(n == undefined)n=1; if(n == 'bottom')this.level(n); else { var previous=objectLayer(this).objs[this.optns.number-n]; if(previous!==undefined) { n=this._level-(previous._level-1); } this.level(this._level-n); } return this; } this.level=function(n) { if(n == undefined)return this._level; var layer=objectLayer(this); if(n=='bottom') { if(this.optns.number==0)n=this._level; else n=layer.objs[0]._level-1; } if(n=='top') { if(this.optns.number==layer.objs.length)n=this._level; else n=layer.objs[layer.objs.length-1]._level+1; } this._level=n; layer.optns.anyObjLevelChanged = true; redraw(this); return this; } this.del=function() { this.optns.deleted=true; objectLayer(this).optns.anyObjDeleted = true; redraw(this); } this.focus=function(fn) { if(fn===undefined) { this.optns.focused=true; if(typeof this.onfocus=='function')this.onfocus(); } else this.onfocus=fn; return this; } this.blur=function(fn) { if(fn===undefined) { this.optns.focused=false; if(typeof this.onblur == 'function')this.onblur(); } else this.onblur=fn; return this; } this.click= function(fn) { return setMouseEvent.call(this,fn,'click'); } this.dblclick = function(fn) { return setMouseEvent.call(this,fn,'dblclick'); } this.keypress= function(fn) { return setKeyEvent.call(this,fn,'onkeypress'); } this.keydown= function(fn) { return setKeyEvent.call(this,fn,'onkeydown'); } this.keyup= function(fn) { return setKeyEvent.call(this,fn,'onkeyup'); } this.mousedown= function(fn) { return setMouseEvent.call(this,fn,'mousedown'); } this.mouseup= function(fn) { return setMouseEvent.call(this,fn,'mouseup'); } this.mousemove= function(fn) { return setMouseEvent.call(this,fn,'mousemove'); } this.mouseover= function(fn) { return setMouseEvent.call(this,fn,'mouseover'); } this.mouseout= function(fn) { return setMouseEvent.call(this,fn,'mouseout'); } this.attr=function(parameter,value) { if(typeof parameter==='object') var parameters=parameter; else { if(value===undefined) return this['_'+parameter]; parameters={}; parameters[parameter]=value; } return this.animate(parameters); } this.queue=function(){ var animateQueueLength=this.animateQueue.length, queue,i,j,duration=0,longFn=0,fn,args=arguments; for (i=0;i<args.length;i++) { if(typeof args[i]=='function'){ args[i].apply(this); args[i]=false; i++; if(this.animateQueue.length>animateQueueLength) { for (j=animateQueueLength;j<this.animateQueue.length;j++) { queue=this.animateQueue[j]; if(queue.duration!==undefined){ if(queue.duration>duration) { duration=queue.duration; longFn=j; } break; } } if(duration){ queue=this.animateQueue[longFn]; if(queue.animateFn){ fn=queue.animateFn; queue.animateFn=function(){ fn.apply(this); this.queue.apply(this,args) } } else queue.animateFn=function(){this.queue.apply(this,args)}; break; } } } } } this.stop=function(jumpToEnd,runCallbacks) { this.optns.animated=false; if(runCallbacks===undefined)runCallbacks=false; if(jumpToEnd===undefined)jumpToEnd=false; for(var q=0;q<this.animateQueue.length;q++) { var queue=this.animateQueue[q]; if(runCallbacks)queue.animateFn.call(this); if(jumpToEnd) for(var key in queue) { if(queue[key]['from']!==undefined) { this[key]=queue[key]['to']; animateTransforms(key,this,queue); } } } this.animateQueue=[]; return this; } this.animate=function(options,duration,easing,onstep,fn) { if(duration===undefined)duration=1; else { if(typeof duration == 'function') { fn=duration; duration=1; } if(typeof duration == 'object') { easing=duration; duration=1; } } if (easing===undefined)easing={fn:'linear',type:'in'}; else { if(typeof easing == 'function') { fn=easing; easing={fn:'linear',type:'in'}; } if (easing.type===undefined)easing.type='in'; } if(onstep===undefined)onstep=false; else { if(typeof onstep == 'function') { fn=onstep; onstep=false; } } if(options.scale!==undefined) { this._scaleX=this._scaleY=1; if(typeof options.scale!='object') { options.scaleX=options.scaleY=options.scale; } else { options.scaleX=options.scale.x||1; options.scaleY=options.scale.y||1; } } if(options.translate!==undefined) { this._translateX=this._translateY=0; if(typeof options.translate!='object') { options.translateX=options.translateY=options.translate; } else { options.translateX=options.translate.x||0; options.translateY=options.translate.y||0; } options.translate=undefined; } if(options.translateTo!==undefined) { var point=this.position(); this._translateToX=point.x; this._translateToY=point.y; if(typeof options.translateTo!='object') { options.translateToX=options.translateToY=options.translateTo; } else { options.translateToX=options.translateTo.x||0; options.translateToY=options.translateTo.y||0; } options.translateTo=undefined; } if(options.rotate!==undefined) { options.rotateAngle=options.rotate.angle; this._rotateAngle=0; this._rotateX=options.rotate.x||0; this._rotateY=options.rotate.y||0; options.rotate=undefined; } if(options.color !== undefined) { var colorKeeper=parseColor(options.color); if(colorKeeper.color.notColor) this.optns.color.notColor=colorKeeper.color.notColor; else { options.colorR=colorKeeper.r; options.colorG=colorKeeper.g; options.colorB=colorKeeper.b; options.alpha=colorKeeper.a; } options.color = undefined; } if(options.shadowColor !== undefined) { colorKeeper=parseColor(options.shadowColor); options.shadowColorR=colorKeeper.r; options.shadowColorG=colorKeeper.g; options.shadowColorB=colorKeeper.b; options.shadowColorA=colorKeeper.a; options.shadowColor = undefined; } if(duration>1) { var queue=this.animateQueue[this.animateQueue.length]={animateKeyCount:0}; queue.animateFn=fn||false; this.optns.animated=true; queue.duration=duration; queue.step=0; queue.easing=easing; queue.onstep=onstep; } for(var key in options) { if(this['_'+key] !== undefined && options[key]!==undefined) { var keyValue=options[key],privateKey='_'+key; if(keyValue!=this[privateKey]) { if(keyValue.charAt) { if(key=='string')this._string=keyValue; else if(keyValue.charAt(1)=='=') { keyValue=this[privateKey]+parseInt(keyValue.charAt(0)+'1')*parseInt(keyValue.substr(2)); } else if(!regHasLetters.test(keyValue))keyValue=parseInt(keyValue); else this[privateKey]=keyValue; } if(duration==1)this[privateKey]=keyValue; else { queue[privateKey]={ from:this[privateKey], to:keyValue, prev:0 } queue.animateKeyCount++; } } } } if(duration==1) { if(options['rotateAngle']) this.rotate(this._rotateAngle,this._rotateX,this._rotateY); if(options['translateX']||options['translateY']) this.translate(this._translateX,this._translateY); if(options['translateToX']||options['translateToY']) this.translate(this._translateToX,this._translateToY); if(options['scaleX']||options['scaleY']) this.scale(this._scaleX,this._scaleY); } redraw(this); return this; } this.matrix=function(m) { if(m===undefined)return [[this._transform11,this._transform21,this._transformdx],[this._transform12,this._transform22,this._transformdy]]; this._transform11=m[0][0]; this._transform21=m[0][1]; this._transform12=m[1][0]; this._transform22=m[1][1]; this._transformdx=m[0][2]; this._transformdy=m[1][2]; return this; } this.translateTo=function(newX,newY,duration,easing,onstep,fn) { if(duration!==undefined) return this.animate({translateTo:{x:newX,y:newY}},duration,easing,onstep,fn); var point=this.position(), x=0,y=0; if(newX!==undefined) x=newX-point.x; if(newY!==undefined) y=newY-point.y; return this.translate(x,y); } this.translate=function(x,y,duration,easing,onstep,fn) { if(duration!==undefined) return this.animate({translate:{x:x,y:y}},duration,easing,onstep,fn); this.optns.translateMatrix=multiplyM(this.optns.translateMatrix,[[1,0,x],[0,1,y]]); changeMatrix(this); return this; } this.scale=function(x,y,duration,easing,onstep,fn) { if(duration!==undefined) return this.animate({scale:{x:x,y:y}},duration,easing,onstep,fn); if(y===undefined)y=x; this.optns.scaleMatrix=multiplyM(this.optns.scaleMatrix,[[x,0,this._x*(1-x)],[0,y,this._y*(1-y)]]); changeMatrix(this); return this; } this.rotate=function(x,x1,y1,duration,easing,onstep,fn) { if(duration!==undefined) return this.animate({rotate:{angle:x,x:x1,y:y1}},duration,easing,onstep,fn); x=x/radian; var cos=m_cos(x), sin=m_sin(x), translateX=0, translateY=0; if(x1!==undefined) { if(x1=='center') { var point=this.getCenter('poor'); if(y1===undefined) { x1=point.x; y1=point.y; } else { x1=point.x+y1.x; y1=point.y+y1.y; } } translateX=-x1*(cos-1)+y1*sin; translateY=-y1*(cos-1)-x1*sin; } this.optns.rotateMatrix=multiplyM(this.optns.rotateMatrix,[[cos,-sin,translateX],[sin,cos,translateY]]); changeMatrix(this); return this; } this.transform=function(m11,m12,m21,m22,dx,dy,reset) { if(m11===undefined)return this.matrix(); var optns=this.optns; if(reset!==undefined) { optns.transformMatrix=[[m11,m21,dx],[m12,m22,dy]]; optns.rotateMatrix=[[1,0,0],[0,1,0]]; optns.scaleMatrix=[[1,0,0],[0,1,0]]; optns.translateMatrix=[[1,0,0],[0,1,0]]; } else { optns.transformMatrix=multiplyM(optns.transformMatrix,[[m11,m21,dx],[m12,m22,dy]]); } changeMatrix(this); return this; } this.beforeDraw=function(canvasOptns) { if(!this._visible)return false; var ctx=canvasOptns.ctx; ctx.save(); if(this.optns.clipObject) { var clipObject=this.optns.clipObject; clipObject._visible=true; if (clipObject.optns.animated)animating.call(clipObject,canvasOptns); clipObject.setOptns(ctx); ctx.beginPath(); clipObject.draw(ctx); ctx.clip(); } this.setOptns(ctx); if (this.optns.animated)animating.call(this,canvasOptns); ctx.beginPath(); return true; } this.clip=function(object) { if(object===undefined)return this.optns.clipObject; objectLayer(this).objs.splice(object.optns.number,1); this.optns.clipObject=object; return this; } this.afterDraw=function(optns) { optns.ctx.closePath(); checkEvents(this,optns); optns.ctx.restore(); if(this.optns.clipObject) { proto.shape.prototype.afterDraw.call(this.optns.clipObject,optns); } } this.isPointIn=function(x,y,global) { var canvasOptns=objectCanvas(this).optns, ctx=canvasOptns.ctx, thisAnimated=false, optns=this.optns, clipAnimated=false; if(global!==undefined) { x-=canvasOptns.x; y-=canvasOptns.y; } if(optns.animated)thisAnimated=true; optns.animated=false; if(optns.clipObject) { var clipObject=optns.clipObject, clipOptns=clipObject.optns; if(clipOptns.animated) { clipAnimated=true; clipOptns.animated=false; } } objectLayer(this).setOptns(ctx); this.beforeDraw(canvasOptns); this.draw(ctx); var point=isPointInPath(this,x,y); ctx.closePath(); ctx.restore(); ctx.setTransform(1,0,0,1,0,0); optns.animated=thisAnimated; if(clipAnimated) { clipOptns.animated=clipAnimated; } return point; } this.layer=function(idLayer) { return layer(idLayer,this,'objs'); } this.canvas=function(idCanvas) { return canvas(idCanvas,this,'objs'); } this.draggable=function(object,params,drag) { if(params===undefined && typeof object=='object' && object.optns===undefined) { params=object.params; drag=object.drag; var start=object.start, stop=object.stop, disabled=object.disabled; object=object.object; } var dragObj=this; var dragOptns=this.optns.drag; if(typeof params==='function') { drag=params; params=undefined; } if(typeof object=='function') { drag=object; object=undefined; } dragOptns.shiftX=0; dragOptns.shiftY=0; if(params!==undefined) { if(params.shiftX!==undefined){dragOptns.shiftX=params.shiftX;params.shiftX=undefined;} if(params.shiftY!==undefined){dragOptns.shiftY=params.shiftY;params.shiftY=undefined;} } if(object!==undefined) { if(object.id)dragObj=(params===undefined)? object.visible(false) : object.animate(params).visible(false); if(object=='clone') { dragObj=this.clone(params).visible(false); dragOptns.type='clone'; } } dragOptns.val=true; dragOptns.x=this._x; dragOptns.y=this._y; dragOptns.dx=this._transformdx; dragOptns.dy=this._transformdy; dragOptns.object=dragObj; dragOptns.params=params; dragOptns.drag=drag||false; dragOptns.start=start||false; dragOptns.stop=stop||false; dragOptns.disabled=disabled||false; var optns=objectCanvas(this).optns; optns.mousemove.val=true; optns.mousedown.val=true; optns.mouseup.val=true; return this; } this.droppable=function(fn) { this.optns.drop.val=true; if(fn!==undefined)this.optns.drop.fn=fn; return this; } this.name = function(name) { return this.attr('name',name); } this.hasName = function(name){ var namesArray = this.attr('name').split(' '), i = 0; while(i < namesArray.length){ if(namesArray[i] === name){ return true; } i++; } return false; } this.addName = function(name) { var namesArray = this.attr('name').split(' '), i = 0; while(i < namesArray.length){ if(namesArray[i] === name){ return this; } i++; } namesArray.push(name); return this.attr('name', namesArray.join(' ')); } this.removeName = function(name) { var namesArray = this.attr('name').split(' '), i = 0; while(i < namesArray.length){ if(namesArray[i] === name){ namesArray.splice(i, 1); return this.attr('name', namesArray.join(' ')); } i++; } return this; } this.visible=function(visibility) { return this.attr('visible',visibility); } this.composite=function(composite) { return this.attr('composite',composite); } this.id=function(id) { if(id===undefined)return this.optns.id; this.optns.id=id; return this; } this.opacity=function(n) { return this.attr('opacity',n); } this.fadeIn=function(duration,easing,onstep,fn) { return this.fadeTo(1,duration,easing,onstep,fn); } this.fadeOut=function(duration,easing,onstep,fn) { return this.fadeTo(0,duration,easing,onstep,fn); } this.fadeTo=function(val,duration,easing,onstep,fn) { if(duration===undefined)duration=600; return this.animate({opacity:val},duration,easing,onstep,fn); } this.fadeToggle=function(duration,easing,onstep,fn) { if(this._opacity) this.fadeOut(duration,easing,onstep,fn); else this.fadeIn(duration,easing,onstep,fn); return this; } this.instanceOf=function(name) { if(name===undefined)return this._proto; return this instanceof proto[name]; } this.base=function(x,y,service) { if(typeof x == 'object'){ x=checkDefaults(x,{x:0,y:0,service:false}); service=x.service; y=x.y; x=x.x; } else{if(service===undefined)service=false;} var canvasItem=canvases[lastCanvas]; this.optns={ animated:false, clipObject:false, drop:{val:false,fn:function(){}}, drag:{val:false}, layer:{id:canvasItem.optns.id+"Layer0",number:0}, canvas:{number:0}, focused:false, buffer:{val:false}, rotateMatrix:[[1,0,0],[0,1,0]], scaleMatrix:[[1,0,0],[0,1,0]], translateMatrix:[[1,0,0],[0,1,0]], transformMatrix:[[1,0,0],[0,1,0]] } this.animateQueue = []; this._x=x; this._y=y; if(service==false && canvasItem!==undefined && canvasItem.layers[0]!==undefined) { this.optns.layer.number=0; this.optns.canvas.number=lastCanvas; var layer=objectLayer(this), limit=layer.objs.length; this.optns.number=limit; this._level=limit?(layer.objs[limit-1]._level+1):0; layer.objs[limit]=this; this.optns.layer.id=layer.optns.id; redraw(this); } return this; } this._visible=true; this._composite='source-over'; this._name=""; this._opacity=1; this._shadowX=0; this._shadowY=0; this._shadowBlur= 0; this._shadowColor= 'rgba(0,0,0,0)'; this._shadowColorR= 0; this._shadowColorG= 0; this._shadowColorB= 0; this._shadowColorA= 0; this._shadowColorRPrev= 0; this._shadowColorGPrev= 0; this._shadowColorBPrev= 0; this._shadowColorAPrev= 0; this._translateX=0; this._translateY=0; this._scaleX=1; this._scaleY=1; this._rotateAngle=0; this._rotateX=0; this._rotateY=0; this._transform11=1; this._transform12=0; this._transform21=0; this._transform22=1; this._transformdx=0; this._transformdy=0; this._matrixChanged=false; } proto.object.prototype=new proto.object(); proto.shape=function() { this.color = function(color) { if (color===undefined)return [this._colorR,this._colorG,this._colorB,this._alpha]; return this.attr('color',color); } this.lineStyle = function(options) { return this.attr(options); } this.setOptns = function(ctx) { proto.shape.prototype.setOptns.call(this,ctx); ctx.lineWidth = this._lineWidth; ctx.lineCap = this._cap; ctx.lineJoin = this._join; ctx.miterLimit = this._miterLimit; var color=this.optns.color; if(color.notColor===undefined){ var rInt = parseInt(this._colorR), gInt = parseInt(this._colorG), bInt = parseInt(this._colorB), aInt = parseInt(this._alpha * 100) / 100; if (this._colorRPrev !== rInt || this._colorGPrev !== gInt || this._colorBPrev !== bInt || this._alphaPrev !== aInt) { color.val = this._color = 'rgba(' + rInt + ', ' + gInt + ', ' + bInt + ', ' + aInt + ')'; this._colorRPrev = rInt; this._colorGPrev = gInt; this._colorBPrev = bInt; this._alphaPrev = aInt; } else { color.val = this._color; } } else { var notColor=color.notColor; var notColorLayer=canvases[notColor.canvas].layers[notColor.layer]; if(notColorLayer.grdntsnptrns[notColor.level]!==undefined){color.val=notColorLayer.grdntsnptrns[notColor.level].val;} } if(this._fill) ctx.fillStyle = color.val; else ctx.strokeStyle = color.val; } this.afterDraw=function(optns) { if(this._fill) optns.ctx.fill(); else optns.ctx.stroke(); proto.shape.prototype.afterDraw.call(this,optns); } this.base=function(x) { if(x===undefined)x={}; if(x.color===undefined)x.color='rgba(0,0,0,1)'; else { if(!x.color.charAt && x.color.id===undefined && x.color.r===undefined) { x.fill=x.color; x.color='rgba(0,0,0,1)'; } } x=checkDefaults(x,{color:'rgba(0,0,0,1)',fill:0}); proto.shape.prototype.base.call(this,x); this._fill=x.fill; this.optns.color={val:x.color,notColor:undefined}; return this.color(x.color); } this._colorR=0; this._colorG=0; this._colorB=0; this._alpha=0; this._colorRPrev=0; this._colorGPrev=0; this._colorBPrev=0; this._alphaPrev=0; this._color = 'rgba(0,0,0,0)'; this._lineWidth = 1; this._cap = 'butt'; this._join = 'miter'; this._miterLimit= 1; } proto.shape.prototype=new proto.object; proto.lines=function() { this.getCenter=function(type) { var point={ x:this._x0, y:this._y0 }; for(var i=1;i<this.shapesCount;i++) { point.x+=this['_x'+i]; point.y+=this['_y'+i]; } point.x=point.x/this.shapesCount; point.y=point.y/this.shapesCount; return getCenter(this,point,type); } this.position=function(){ return multiplyPointM(this._x0,this._y0,multiplyM(this.matrix(),objectLayer(this).matrix())); } this.getRect=function(type){ var minX, minY, maxX=minX=this._x0, maxY=minY=this._y0; for(var i=1;i<this.shapesCount;i++) { if(maxX<this['_x'+i])maxX=this['_x'+i]; if(maxY<this['_y'+i])maxY=this['_y'+i]; if(minX>this['_x'+i])minX=this['_x'+i]; if(minY>this['_y'+i])minY=this['_y'+i]; } var points={x:minX,y:minY,maxX-minX,height:maxY-minY}; return getRect(this,points,type); } this.addPoint=function(){ redraw(this); var names=this.pointNames; for(var i=0;i<names.length;i++) this[names[i]+this.shapesCount]=arguments[i]; this.shapesCount++; return this; } this.delPoint=function(x,y,radius){ redraw(this); if(y===undefined) { var points=this.points(); points.splice(x,1) this.points(points); } else{ radius=radius||0; for(var j=0;j<this.shapesCount;j++) if(this['_x'+j]<x+radius && this['_x'+j]>x-radius && this['_y'+j]<y+radius && this['_y'+j]<y+radius) { this.delPoint(j); j--; } } return this; } this.points=function(points) { var names=this.pointNames; if(points===undefined){ points=[]; for(var j=0;j<this.shapesCount;j++) { points[j]=[]; for(var i=0;i<names.length;i++) points[j][i]=this[names[i]+j]; } return points; } redraw(this); var oldCount=this.shapesCount; this.shapesCount=points.length; for(j=0;j<this.shapesCount;j++) for(i=0;i<names.length;i++) this[names[i]+j]=points[j][i]; for(j=this.shapesCount;j<oldCount;j++) for(i=0;i<names.length;i++) this[names[i]+j]=undefined; return this; } this.base=function(points,color,fill) { if(points!==undefined) { if(typeof points.pop == 'function') points={points:points,color:color,fill:fill}; } proto.lines.prototype.base.call(this,points); this.shapesCount=0; if(points!==undefined) if(points.points!==undefined) this.points(points.points); return this; } } proto.lines.prototype=new proto.shape; proto.line=function(){ this.draw=function(ctx) { if(this._x0===undefined)return; ctx.moveTo(this._x0,this._y0); for(var j=1;j<this.shapesCount;j++) { ctx.lineTo(this['_x'+j],this['_y'+j]); } } this.base=function(points,color,fill) { proto.line.prototype.base.call(this,points,color,fill); return this; } this._proto='line'; this.pointNames=['_x','_y']; } proto.line.prototype=new proto.lines; proto.qCurve=function(){ this.draw=function(ctx) { if(this._x0===undefined)return; ctx.moveTo(this._x0,this._y0); for(var j=1;j<this.shapesCount;j++) { ctx.quadraticCurveTo(this['_cp1x'+j],this['_cp1y'+j],this['_x'+j],this['_y'+j]); } } this.base=function(points,color,fill) { proto.qCurve.prototype.base.call(this,points,color,fill); return this; } this._proto='qCurve'; this.pointNames=['_x','_y','_cp1x','_cp1y']; } proto.qCurve.prototype=new proto.lines; proto.bCurve=function(){ this.draw=function(ctx) { if(this._x0===undefined)return; ctx.moveTo(this._x0,this._y0); for(var j=1;j<this.shapesCount;j++) { ctx.bezierCurveTo(this['_cp1x'+j],this['_cp1y'+j],this['_cp2x'+j],this['_cp2y'+j],this['_x'+j],this['_y'+j]); } } this.base=function(points,color,fill) { proto.bCurve.prototype.base.call(this,points,color,fill); return this; } this._proto='bCurve'; this.pointNames=['_x','_y','_cp1x','_cp1y','_cp2x','_cp2y']; } proto.bCurve.prototype=new proto.lines; proto.circle = function () { this.getCenter = function (type) { return getCenter(this, {x:this._x, y:this._y}, type); } this.getRect = function (type) { var points = {x:Math.floor(this._x - this._radius), y:Math.floor(this._y - this._radius)}; points.width = points.height = Math.ceil(this._radius) * 2; return getRect(this, points, type); } this.draw = function (ctx) { ctx.arc(this._x, this._y, this._radius, 0, pi2, true); } this.base = function (x, y, radius, color, fill) { if (typeof x != 'object') x = {x:x, y:y, radius:radius, color:color, fill:fill}; x = checkDefaults(x, {radius:0}); proto.circle.prototype.base.call(this, x); this._radius = x.radius; return this; } this._proto = 'circle'; } proto.circle.prototype = new proto.shape; proto.rect = function () { this.getRect = function (type) { return getRect(this, {x:this._x, y:this._y, this._width, height:this._height}, type); } this.draw = function (ctx) { ctx.rect(this._x, this._y, this._width, this._height); } this.base = function (x, y, width, height, color, fill) { if (typeof x != 'object') x = {x:x, y:y, width, height:height, color:color, fill:fill}; x = checkDefaults(x, {0, height:0}); proto.rect.prototype.base.call(this, x); this._width = x.width; this._height = x.height; return this; } this._proto = 'rect'; } proto.rect.prototype = new proto.shape; proto.arc = function () { this.getRect = function (type) { var points = {x:this._x, y:this._y}, startAngle = this._startAngle, endAngle = this._endAngle, radius = this._radius, startY = m_floor(m_sin(startAngle / radian) * radius), startX = m_floor(m_cos(startAngle / radian) * radius), endY = m_floor(m_sin(endAngle / radian) * radius), endX = m_floor(m_cos(endAngle / radian) * radius), positiveXs = startX > 0 && endX > 0, negtiveXs = startX < 0 && endX < 0, positiveYs = startY > 0 && endY > 0, negtiveYs = startY < 0 && endY < 0; points.width = points.height = radius; if ((this._anticlockwise && startAngle < endAngle) || (!this._anticlockwise && startAngle > endAngle)) { if (((negtiveXs || (positiveXs && (negtiveYs || positiveYs)))) || (startX == 0 && endX == 0)) { points.y -= radius; points.height += radius; } else { if (positiveXs && endY < 0 && startY > 0) { points.y += endY; points.height += endY; } else if (endX > 0 && endY < 0 && startX < 0) { points.y += m_min(endY, startY); points.height -= m_min(endY, startY); } else { if (negtiveYs)points.y -= m_max(endY, startY); else points.y -= radius; points.height += m_max(endY, startY); } } if (((positiveYs || (negtiveYs && (negtiveXs || positiveXs) ))) || (startY == 0 && endY == 0)) { points.x -= radius; points.width += radius; } else { if (endY < 0 && startY > 0) { points.x += m_min(endX, startX); points.width -= m_min(endX, startX); } else { if (negtiveXs)points.x -= m_max(endX, startX); else points.x -= radius; points.width += m_max(endX, startX); } } } else { positiveXs = startX >= 0 && endX >= 0; positiveYs = startY >= 0 && endY >= 0; negtiveXs = startX <= 0 && endX <= 0; negtiveYs = startY <= 0 && endY <= 0; if (negtiveYs && positiveXs) { points.x += m_min(endX, startX); points.width -= m_min(endX, startX); points.y += m_min(endY, startY); points.height += m_max(endY, startY); } else if (negtiveYs && negtiveXs) { points.x += m_min(endX, startX); points.width += m_max(endX, startX); points.y += m_min(endY, startY); points.height += m_max(endY, startY); } else if (negtiveYs) { points.x += m_min(endX, startX); points.width += m_max(endX, startX); points.y -= radius; points.height += m_max(endY, startY); } else if (positiveXs && positiveYs) { points.x += m_min(endX, startX); points.width = m_abs(endX - startX); points.y += m_min(endY, startY); points.height -= m_min(endY, startY); } else if (positiveYs) { points.x += m_min(endX, startX); points.width = m_abs(endX) + m_abs(startX); points.y += m_min(endY, startY); points.height -= m_min(endY, startY); } else if (negtiveXs) { points.x -= radius; points.width += m_max(endX, startX); points.y -= radius; points.height += m_max(endY, startY); } else if (positiveXs) { points.x -= radius; points.width += m_max(endX, startX); points.y -= radius; points.height += radius; } } return getRect(this, points, type); } this.draw = function (ctx) { ctx.arc(this._x, this._y, this._radius, this._startAngle / radian, this._endAngle / radian, this._anticlockwise); } this.base = function (x, y, radius, startAngle, endAngle, anticlockwise, color, fill) { if (anticlockwise !== undefined) { if (anticlockwise.charAt)color = anticlockwise; if (anticlockwise)anticlockwise = true; else anticlockwise = false; } if (typeof x != 'object') x = {x:x, y:y, radius:radius, startAngle:startAngle, endAngle:endAngle, anticlockwise:anticlockwise, color:color, fill:fill}; x = checkDefaults(x, {radius:0, startAngle:0, endAngle:0, anticlockwise:true}); proto.arc.prototype.base.call(this, x); this._radius = x.radius; this._startAngle = x.startAngle; this._endAngle = x.endAngle; this._anticlockwise = x.anticlockwise; return this; } this._proto = 'arc'; } proto.arc.prototype = new proto.shape; proto.text = function () { this.font = function (font) { return this.attr('font', font); } this._font = "10px sans-serif"; this.align = function (align) { return this.attr('align', align); } this._align = "start"; this.baseline = function (baseline) { return this.attr('baseline', baseline); } this._baseline = "alphabetic"; this.string = function (string) { return this.attr('string', string); } this.position = function () { var points = {x:this._x, y:this._y}, ctx = objectCanvas(this).optns.ctx; points.height = parseInt(this._font.match(regNumsWithMeasure)[0]); points.y -= points.height; ctx.save(); ctx.textBaseline = this._baseline; ctx.font = this._font; ctx.textAlign = this._align; points.width = ctx.measureText(this._string).width; ctx.restore(); return getRect(this, points); } this.getRect = function (type) { var points = {x:this._x, y:this._y}, ctx = objectCanvas(this).optns.ctx; points.height = parseInt(this._font.match(regNumsWithMeasure)[0]); points.y -= points.height; ctx.save(); ctx.textBaseline = this._baseline; ctx.font = this._font; ctx.textAlign = this._align; points.width = ctx.measureText(this._string).width; if (this._align == 'center')points.x -= points.width / 2; if (this._align == 'right')points.x -= points.width; ctx.restore(); return getRect(this, points, type); } this.setOptns = function (ctx) { proto.text.prototype.setOptns.call(this, ctx); ctx.textBaseline = this._baseline; ctx.font = this._font; ctx.textAlign = this._align; } this.draw = function (ctx) { if (this._maxWidth === false) { if (this._fill)ctx.fillText(this._string, this._x, this._y); else ctx.strokeText(this._string, this._x, this._y); } else { if (this._fill) ctx.fillText(this._string, this._x, this._y, this._maxWidth); else ctx.strokeText(this._string, this._x, this._y, this._maxWidth); } } this.base = function (string, x, y, maxWidth, color, fill) { if (maxWidth !== undefined) { if (maxWidth.charAt) { if (color !== undefined)fill = color; color = maxWidth; maxWidth = false; } } if (typeof string != 'object') string = {string:string, x:x, y:y, maxWidth:maxWidth, color:color, fill:fill}; string = checkDefaults(string, {string:'', maxWidth:false, fill:1}); proto.text.prototype.base.call(this, string); this._string = string.string; this._maxWidth = string.maxWidth; return this; } this._proto = 'text'; } proto.text.prototype = new proto.shape; proto.grdntsnptrn=function() { this.layer=function(idLayer) { return layer(idLayer,this,'grdntsnptrns'); } this.canvas=function(idCanvas) { return canvas(idCanvas,this,'grdntsnptrns'); } var tmpObj=new proto.object; this.animate=tmpObj.animate; this.attr=tmpObj.attr; this.id=tmpObj.id; this.name=tmpObj.name; this.level=tmpObj.level; this.base=function() { this.animateQueue=[]; this.optns={ animated:false, name:"", layer:{id:canvases[0].optns.id+'Layer_0',number:0}, canvas:{number:0}, visible:true } this.optns.layer.id=canvases[lastCanvas].optns.id+'Layer_0'; this.optns.layer.number=0 this.optns.canvas.number=lastCanvas; var grdntsnptrnsArray=canvases[lastCanvas].layers[0].grdntsnptrns; this._level=grdntsnptrnsArray.length; grdntsnptrnsArray[this._level]=this; redraw(this); } return this; } proto.gradients=function() { this.colorStopsCount=0; this.paramNames=['_pos','_colorR','_colorG','_colorB','_alpha']; this.addColorStop=function(pos,color){ redraw(this); var colorKeeper = parseColor(color); var i=this.colorStopsCount; this['_pos'+i] = pos; this['_colorR'+i] = colorKeeper.r; this['_colorG'+i] = colorKeeper.g; this['_colorB'+i] = colorKeeper.b; this['_alpha'+i] = colorKeeper.a; this.colorStopsCount++; return this; } this.animate=function(parameters,duration,easing,onstep,fn){ for(var key in parameters) { if(key.substr(0,5)=='color') { var i=key.substring(5); var colorKeeper=parseColor(parameters[key]); parameters['colorR'+i] = colorKeeper.r; parameters['colorG'+i] = colorKeeper.g; parameters['colorB'+i] = colorKeeper.b; parameters['alpha'+i] = colorKeeper.a; } } proto.gradients.prototype.animate.call(this,parameters,duration,easing,onstep,fn); } this.delColorStop=function(i) { redraw(this); var colorStops=this.colorStops(); colorStops.splice(i,1); if(colorStops.length>0)this.colorStops(colorStops); else this.colorStopsCount=0; return this; } this.colorStops=function(array) { var names=this.paramNames; if(array===undefined){ array=[]; for(var j=0;j<this.colorStopsCount;j++) { array[j]=[]; for(var i=0;i<names.length;i++) array[j][i]=this[names[i]+j]; } return array; } redraw(this); var oldCount=this.colorStopsCount; var limit=array.length; if(array[0].length==2) for(j=0;j<limit;j++) this.addColorStop(array[j][0], array[j][1]); else for(j=0;j<limit;j++) for(i=0;i<names.length;i++) this[names[i]+j]=array[j][i]; for(j=limit;j<oldCount;j++) for(i=0;i<names.length;i++) this[names[i]+j]=undefined; this.colorStopsCount=limit; return this; } this.base=function(colors) { proto.gradients.prototype.base.call(this); if (colors==undefined) return this; else return this.colorStops(colors); } } proto.gradients.prototype=new proto.grdntsnptrn; proto.pattern = function() { this.create = function(canvasOptns) { if(this.optns.animated)animating.call(this,canvasOptns); this.val = canvasOptns.ctx.createPattern(this._img,this._type); } this.base=function(image,type) { if(image.onload) image={image:image,type:type}; image=checkDefaults(image,{type:'repeat'}); proto.pattern.prototype.base.call(this); this._img=image.image; this._type=image.type; return this; } this._proto='pattern'; } proto.pattern.prototype=new proto.grdntsnptrn; proto.lGradient=function() { this.create = function(canvasOptns) { if(this.optns.animated)animating.call(this,canvasOptns); this.val=canvasOptns.ctx.createLinearGradient(this._x1,this._y1,this._x2,this._y2); for(var i=0;i<this.colorStopsCount;i++) { this.val.addColorStop(this['_pos'+i],'rgba('+parseInt(this['_colorR'+i])+','+parseInt(this['_colorG'+i])+','+parseInt(this['_colorB'+i])+','+this['_alpha'+i]+')'); } } this.base=function(x1,y1,x2,y2,colors) { if(typeof x1!=='object') x1={x1:x1,y1:y1,x2:x2,y2:y2,colors:colors}; x1=checkDefaults(x1,{x1:0,y1:0,x2:0,y2:0}) proto.lGradient.prototype.base.call(this,x1.colors); this._x1 = x1.x1; this._y1 = x1.y1; this._x2 = x1.x2; this._y2 = x1.y2; return this; } this._proto='lGradient'; } proto.lGradient.prototype=new proto.gradients; proto.rGradient=function() { this.create = function(canvasOptns) { if(this.optns.animated)animating.call(this); this.val=canvasOptns.ctx.createRadialGradient(this._x1,this._y1,this._r1,this._x2,this._y2,this._r2); for(var i=0;i<this.colorStopsCount;i++) { this.val.addColorStop(this['_pos'+i],'rgba('+parseInt(this['_colorR'+i])+','+parseInt(this['_colorG'+i])+','+parseInt(this['_colorB'+i])+','+this['_alpha'+i]+')'); } } this.base=function(x1,y1,r1,x2,y2,r2,colors) { if(typeof x1!=='object') x1={x1:x1,y1:y1,r1:r1,x2:x2,y2:y2,r2:r2,colors:colors}; x1=checkDefaults(x1,{x1:0,y1:0,r1:0,x2:0,y2:0,r2:0}) proto.rGradient.prototype.base.call(this,x1.colors); this._x1 = x1.x1; this._y1 = x1.y1; this._r1 = x1.r1; this._x2 = x1.x2; this._y2 = x1.y2; this._r2 = x1.r2; return this; } this._proto='rGradient'; } proto.rGradient.prototype=new proto.gradients; proto.layer=function() { this.position=function(){ var objs=this.objs, points,point,i, limit=objs.length; for(i=0;i<limit;i++) { point=objs[i].position(); if(points===undefined)points=point; if(points.x>point.x)points.x=point.x; if(points.y>point.y)points.y=point.y; } return points; } this.getRect=function(type){ var objs=this.objs, points,rect,i, limit=objs.length; if (objs.length==0)return false; if(type=='coords') { for(i=0;i<limit;i++) { rect=objs[i].getRect(type); if(points===undefined)points=rect; if(points[0][0]>rect[0][0])points[0][0]=rect[0][0]; if(points[0][1]>rect[0][1])points[0][1]=rect[0][1]; if(points[1][0]<rect[1][0])points[1][0]=rect[1][0]; if(points[1][1]>rect[1][1])points[1][1]=rect[1][1]; if(points[2][0]>rect[2][0])points[2][0]=rect[2][0]; if(points[2][1]<rect[2][1])points[2][1]=rect[2][1]; if(points[3][0]<rect[3][0])points[3][0]=rect[3][0]; if(points[3][1]<rect[3][1])points[3][1]=rect[3][1]; } return points; } for(i=0;i<limit;i++) { rect=objs[i].getRect(type); rect.right=rect.width+rect.x; rect.bottom=rect.height+rect.y; if(points===undefined)points=rect; if(points.x>rect.x)points.x=rect.x; if(points.y>rect.y)points.y=rect.y; if(points.right<rect.right)points.right=rect.right; if(points.bottom<rect.bottom)points.bottom=rect.bottom; } points.width=points.right-points.x; points.height=points.bottom-points.y; return points; } this.canvas=function(idCanvas) { if (idCanvas===undefined)return this.idCanvas; if(this.optns.canvas.id==idCanvas)return this; var newCanvas=-1,oldCanvas=0,limitC=canvases.length; for(var i=0;i<limitC;i++) { var idCanvasItem=canvases[i].optns.id; if (idCanvasItem==idCanvas)newCanvas=i; if (idCanvasItem==this.optns.canvas.id)oldCanvas=i; } if(newCanvas<0){newCanvas=canvases.length;jCanvaScript.canvas(idCanvas);} this.optns.canvas.id=idCanvas; this.optns.canvas.number=newCanvas; canvases[oldCanvas].layers.splice(this.optns.number,1); var layersArray=canvases[newCanvas].layers; this._level=this.optns.number=layersArray.length; layersArray[this._level]=this; setLayerAndCanvasToArray(this.objs,this.optns.id,this._level,idCanvas,newCanvas); setLayerAndCanvasToArray(this.grdntsnptrns,this.optns.id,this._level,idCanvas,newCanvas); canvases[newCanvas].optns.redraw=1; return this; } this.up=function(n) { if(n === undefined)n=1; if(n=='top')this.level(n); else { var next=objectCanvas(this).layers[this.optns.number+n]; if(next!==undefined) { n=next._level+1-this._level; } this.level(this._level+n); } return this; } this.down=function(n) { if(n == undefined)n=1; if(n == 'bottom')this.level(n); else { var previous=objectCanvas(this).layers[this.optns.number-n]; if(previous!==undefined) { n=this._level-(previous._level-1); } this.level(this._level-n); } return this; } this.level=function(n) { if(n == undefined)return this._level; var canvas=objectCanvas(this), optns=canvas.optns; if(n=='bottom') if(this.optns.number==0)n=this._level; else n=canvas.layers[0]._level-1; if(n=='top') if(this.optns.number==canvas.layers.length-1)n=this._level; else n=canvas.layers[canvas.layers.length-1]._level+1; this._level=n; optns.anyLayerLevelChanged = true; optns.redraw=1; return this; } this.del=function() { var optns=objectCanvas(this).optns; optns.anyLayerDeleted = true; this.optns.deleted = true; this.draw = false; optns.redraw=1; return; } this.setOptns=function(ctx) { ctx.setTransform(1,0,0,1,0,0); proto.layer.prototype.setOptns.call(this,ctx); return this; } this.afterDraw=function(optns) { optns.ctx.closePath(); optns.ctx.restore(); if(this.optns.clipObject) { proto.layer.prototype.afterDraw.call(this.optns.clipObject,optns); } } this.clone=function(idLayer,params) { var clone=jCanvaScript.layer(idLayer); take(clone,this); take(clone.optns.transformMatrix,this.optns.transformMatrix); take(clone.optns.translateMatrix,this.optns.translateMatrix); take(clone.optns.scaleMatrix,this.optns.scaleMatrix); take(clone.optns.rotateMatrix,this.optns.rotateMatrix); clone.canvas(objectCanvas(this).optns.id); if(params===undefined) return clone; return clone.animate(params); } this.isPointIn=function(x,y,global) { var objs=this.objs,i; for(i=0;i<objs.length;i++) if(objs[i].isPointIn(x,y,global)) return true; return false; } this.opacity=function(n) { var objs=this.objs; for(var i=0;i<objs.length;i++) objs[i].attr('opacity',n); return this; } this.fadeTo=function(val,duration,easing,onstep,fn) { if(duration===undefined)duration=600; var objs=this.objs; for(var i=0;i<objs.length;i++) objs[i].animate({opacity:val},duration,easing,onstep,fn); return this; } this.draw=function(canvasOptns) { var optns=this.optns, bufOptns=optns.buffer, ctx=canvasOptns.ctx; if(bufOptns.val) { ctx.drawImage(bufOptns.cnv,bufOptns.x,bufOptns.y); return this; } for(var i=0;i<this.grdntsnptrns.length;i++) this.grdntsnptrns[i].create(canvasOptns); if(optns.anyObjLevelChanged) { levelChanger(this.objs); optns.anyObjLevelChanged = false; } if(optns.anyObjDeleted) { objDeleter(this.objs); optns.anyObjDeleted = false; } ctx.globalCompositeOperation = optns.gCO; for(i=0;i<this.objs.length;i++) { var object=this.objs[i]; if(typeof (object.draw)=='function') { this.setOptns(ctx); if(object.beforeDraw(canvasOptns)) { if(typeof (object.draw)=='function') { var objBufOptns=object.optns.buffer; if(objBufOptns.val) ctx.drawImage(objBufOptns.cnv,objBufOptns.x,objBufOptns.y); else object.draw(ctx); if(bufOptns.optns) object.afterDraw(bufOptns.optns); else object.afterDraw(canvasOptns); } } } } return this; } this.objects=function(map) { var myGroup=group(),i=0; while(this.objs[i]!==undefined) myGroup.elements[i]=this.objs[i++]; if(map!==undefined) return myGroup.find(map); return myGroup; } this.base=function(idLayer) { var canvas=canvases[lastCanvas], lastCanvasLayers=canvas.layers, lastCanvasOptns=canvas.optns; proto.layer.prototype.base.call(this,0,0,true); var limit=lastCanvasLayers.length; lastCanvasLayers[limit]=this; this.objs = []; this.grdntsnptrns = []; this._level=limit?(lastCanvasLayers[limit-1]._level+1):0; this.optns.number=limit; this.optns.id=idLayer; var thisOptns=this.optns thisOptns.anyObjDeleted= false; thisOptns.anyObjLevelChanged= false; thisOptns.gCO= lastCanvasOptns.gCO; thisOptns.canvas.id=lastCanvasOptns.id; thisOptns.canvas.number=lastCanvas; return this; } this._proto='layer'; } proto.layer.prototype=new proto.object; function layers(idLayer) { var layer=new proto.layer(); return layer.base(idLayer); } proto.imageData=function() { this.filter=function(filterName,filterType) { var filter=imageDataFilters[filterName]; filter.fn.call(this,this._width,this._height,filter.matrix,filterType); return this; }; this.getRect=function(type) { var points={x:this._x,y:this._y,this._width,height:this._height}; return getRect(this,points,type); } this.setPixel=function(x,y,color) { var colorKeeper,index=(x + y * this._width) * 4; if (color.r !== undefined) colorKeeper=color; else if (color[0] !== undefined) if (!color.charAt) colorKeeper={r:color[0],g:color[1],b:color[2],a:color[3]}; else colorKeeper = parseColor(color); this._data[index+0] = colorKeeper.r; this._data[index+1] = colorKeeper.g; this._data[index+2] = colorKeeper.b; this._data[index+3] = colorKeeper.a*255; redraw(this); return this; } this.getPixel=function(x,y) { var index=(x + y * this._width) * 4; return [this._data[index+0],this._data[index+1],this._data[index+2],this._data[index+3]/255]; } this._getX=0; this._getY=0; this.getData=function(x,y,width,height) { this._getX=x; this._getY=y; this._width=width; this._height=height; var ctx=objectCanvas(this).optns.ctx; try{ this._imgData=ctx.getImageData(this._getX,this._getY,this._width,this._height); }catch(e){ netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"); this._imgData=ctx.getImageData(this._getX,this._getY,this._width,this._height); } this._data=this._imgData.data; redraw(this); return this; } this.putData=function(x,y) { if(x!==undefined)this._x=x; if(y!==undefined)this._y=y; this._putData=true; redraw(this); return this; } this.clone=function(){ var clone=proto.imageData.prototype.clone.call(this); clone._imgData=undefined; return clone; } this.draw=function(ctx) { if(this._imgData===undefined) { this._imgData=ctx.createImageData(this._width,this._height); for(var i=0;i<this._width*this._height*4;i++) this._imgData.data[i]=this._data[i]; this._data=this._imgData.data; } if(this._putData) ctx.putImageData(this._imgData,this._x,this._y); } this.base=function(width,height) { proto.imageData.prototype.base.call(this); if(height===undefined) { var oldImageData=width; if(oldImageData._width!==undefined) { width=oldImageData._width; height=oldImageData._height; } else { width=checkDefaults(width,{0,height:0}); height=width.height; width=width.width; } } this._width=width; this._height=height; this._data=[]; for(var i=0;i<this._width;i++) for(var j=0;j<this._height;j++) { var index=(i+j*this._width)*4; this._data[index+0]=0; this._data[index+1]=0; this._data[index+2]=0; this._data[index+3]=0; } return this; } this._putData=false; this._proto='imageData'; } proto.imageData.prototype=new proto.object; proto.image=function() { this.getRect=function(type) { var points={x:this._x,y:this._y,this._width,height:this._height}; return getRect(this,points,type); } this.draw=function(ctx) { ctx.drawImage(this._img,this._sx,this._sy,this._swidth,this._sheight,this._x,this._y,this._width,this._height); } this.base=function(image,x,y,width,height,sx,sy,swidth,sheight) { if(typeof image!='object' || image.src!==undefined || image.nodeName !== undefined) image={image:image,x:x,y:y,width,height:height,sx:sx,sy:sy,sswidth,sheight:sheight}; image=checkDefaults(image,{false,height:false,sx:0,sy:0,sfalse,sheight:false}); if(image.width===false) { image.width=image.image.width; image.height=image.image.height; } if(image.swidth===false) { image.swidth=image.image.width; image.sheight=image.image.height; } proto.image.prototype.base.call(this,image); this._img=image.image; this._width=image.width; this._height=image.height; this._sx=image.sx; this._sy=image.sy; this._swidth=image.swidth; this._sheight=image.sheight; return this; } this._proto='image'; } proto.image.prototype=new proto.object; proto.groups=function() { for(var Class in proto) { if(Class=='group'||Class=='groups')continue; var tmp=new proto[Class]; for(var key in tmp) { if(typeof tmp[key]=='function' && this[key]===undefined) { (function(group,key) { group[key]=function(){ var argumentsClone=[]; var args=[]; var i=0; while(arguments[i]!==undefined) args[i]=arguments[i++]; for(i=0;i<this.elements.length;i++) { var element=this.elements[i]; take(argumentsClone,args); if(typeof element[key]=='function') { element[key].apply(element,argumentsClone); } } return this; } })(this,key); } } } this.reverse=function(){ var tmpArray=this.elements; this.elements=this.unmatchedElements; this.unmatchedElements=tmpArray; return this; } this.end=function(n){ if(this.previousGroup===undefined || n===0)return this; if(n!==undefined)n--; return this.previousGroup.end(n); } this.find=function(map){ var subgroup=group(), attrs=map.attrs, fns=map.fns||[], i,j, element,rel,fn,value1,value2; subgroup.previousGroup=this; for(i=0;i<this.elements.length;i++) { subgroup.elements[i]=this.elements[i]; } if(attrs!==undefined) { for(j in attrs) { if(attrs.hasOwnProperty(j)) { if(typeof attrs[j]!='object') { attrs[j]={val:attrs[j],rel:'=='}; } fns[fns.length]={ fn:'attr', args:[j], val:attrs[j].val, rel:attrs[j].rel }; } } } if(fns.length) { for(i=0;i<subgroup.elements.length;i++) { element=subgroup.elements[i]; for(j=0;j<fns.length;j++) { fn=fns[j]; value2=fn.val; rel=fn.rel; if(typeof element[fn.fn]=='function') value1=element[fn.fn].apply(element,fn.args); else rel='del'; switch(rel) { case '!=': if(!(value1!=value2))rel='del'; break; case '!==': if(!(value1!==value2))rel='del'; break; case '==': if(!(value1==value2))rel='del'; break; case '===': if(!(value1===value2))rel='del'; break; case '>=': if(!(value1>=value2))rel='del'; break; case '<=': if(!(value1<=value2))rel='del'; break; case '>': if(!(value1>value2))rel='del'; break; case '<': if(!(value1<value2))rel='del'; break; case 'typeof': if(!(typeof value1==value2))rel='del'; break; } if(rel=='del') { subgroup.unmatchedElements[subgroup.unmatchedElements.length]=element; subgroup.elements.splice(i,1); i--; break; } } } } return subgroup; } this.base=function(){ this.elements=[]; this.unmatchedElements=[]; return this; } } proto.group=function() { this._proto='group'; }; proto.group.prototype=new proto.groups; function group() { var group=new proto.group; return group.base(); } jCanvaScript.addFunction=function(name,fn,prototype) { proto[prototype||'object'].prototype[name]=fn; return jCanvaScript; } jCanvaScript.addObject=function(name,parameters,drawfn,parent) { proto[name]=function(name){ this.draw=proto[name].draw; this.base=proto[name].base; this._proto=name; }; var protoItem=proto[name]; if(parent===undefined)parent='shape'; protoItem.prototype=new proto[parent]; protoItem.draw=drawfn; protoItem.base=function(name,parameters,args) { protoItem.prototype.base.call(this,parameters); var i=0; for(var key in parameters) { var parameter = (args[i] !== undefined)?args[i]:parameters[key]; this['_'+key]=parameter; if(key=='color')this.color(parameter); i++; } return this; }; (function(name,parameters) { jCanvaScript[name]=function() { var object=new proto[name](name); return object.base(name,parameters,arguments); } })(name,parameters); return jCanvaScript; } jCanvaScript.addAnimateFunction=function(name,fn) { animateFunctions[name]=fn; return jCanvaScript; } jCanvaScript.addImageDataFilter=function(name,properties) { if(imageDataFilters[name]===undefined)imageDataFilters[name]={}; if(properties.fn!==undefined)imageDataFilters[name].fn=properties.fn; if(properties.matrix!==undefined && properties.type===undefined)imageDataFilters[name].matrix=properties.matrix; if(properties.type!==undefined)imageDataFilters[name].matrix[type]=properties.matrix; return jCanvaScript; } jCanvaScript.clear=function(idCanvas) { if(canvases[0]===undefined)return jCanvaScript; if(idCanvas===undefined){canvases[0].clear();return jCanvaScript;} jCanvaScript.canvas(idCanvas).clear(); return jCanvaScript; } jCanvaScript.pause=function(idCanvas) { if(idCanvas===undefined){canvases[0].pause();return jCanvaScript;} jCanvaScript.canvas(idCanvas).pause(); return jCanvaScript; } jCanvaScript.start=function(idCanvas,isAnimated) { jCanvaScript.canvas(idCanvas).start(isAnimated); return jCanvaScript; } jCanvaScript.pattern = function(img,type) { var pattern = new proto.pattern; return pattern.base(img,type); } jCanvaScript.lGradient=function(x1,y1,x2,y2,colors) { var lGrad = new proto.lGradient; return lGrad.base(x1,y1,x2,y2,colors); } jCanvaScript.rGradient=function(x1,y1,r1,x2,y2,r2,colors) { var rGrad = new proto.rGradient; return rGrad.base(x1,y1,r1,x2,y2,r2,colors); } jCanvaScript.line=function(points,color,fill) { var line = new proto.line; return line.base(points,color,fill); } jCanvaScript.qCurve=function(points,color,fill) { var qCurve = new proto.qCurve; return qCurve.base(points,color,fill); } jCanvaScript.bCurve=function(points,color,fill) { var bCurve = new proto.bCurve; return bCurve.base(points,color,fill); } jCanvaScript.imageData=function(width,height) { var imageData=new proto.imageData; return imageData.base(width,height); } jCanvaScript.image=function(img,x,y,width,height,sx,sy,swidth,sheight) { var image=new proto.image; return image.base(img,x,y,width,height,sx,sy,swidth,sheight); } jCanvaScript.circle=function(x,y,radius,color,fill) { var circle=new proto.circle; return circle.base(x,y,radius,color,fill); } jCanvaScript.rect=function(x,y,width,height,color,fill) { var rect = new proto.rect; return rect.base(x,y,width,height,color,fill); } jCanvaScript.arc=function(x,y,radius,startAngle,endAngle,anticlockwise,color,fill) { var arc=new proto.arc; return arc.base(x,y,radius,startAngle,endAngle,anticlockwise,color,fill); } jCanvaScript.text = function(string,x,y,maxWidth,color,fill) { var text=new proto.text; return text.base(string,x,y,maxWidth,color,fill); } jCanvaScript.canvas = function(idCanvas) { if(idCanvas===undefined)return canvases[0]; var limit=canvases.length; for (var i=0;i<limit;i++) if(canvases[i].optns) if(canvases[i].optns.id==idCanvas)return canvases[i]; var canvas={ id:function(id) { if(id===undefined)return this.optns.id; this.optns.id=id; return this; } }; canvases[limit]=canvas; lastCanvas=limit; canvas.cnv=document.getElementById(idCanvas); if ('v'=='v') { if(typeof G_vmlCanvasManager!=='undefined') G_vmlCanvasManager.initElement(canvas.cnv); if(typeof FlashCanvas !=='undefined') FlashCanvas.initElement(canvas.cnv); } canvas.width = function(width){ if(width === undefined) return this.cnv.width; this.optns.width = this.cnv.width = width; this.cnv.style.width = width + 'px'; this.optns.redraw = 1; return this; } canvas.height = function(height){ if(height === undefined) return this.cnv.height; this.optns.heigth = this.cnv.height = height; this.cnv.style.height = height + 'px'; this.optns.redraw = 1; return this; } canvas.optns = { id:idCanvas, number:lastCanvas, ctx: canvas.cnv.getContext('2d'), canvas.cnv.offsetWidth||canvas.cnv.width, height: canvas.cnv.offsetHeight||canvas.cnv.height, anyLayerDeleted: false, anyLayerLevelChanged:false, keyDown:{val:false,code:false}, keyUp:{val:false,code:false}, keyPress:{val:false,code:false}, mousemove:{val:false,x:false,y:false,object:false}, click:{val:false,x:false,y:false,objects:[]}, dblclick:{val:false,x:false,y:false,objects:[]}, mouseup:{val:false,x:false,y:false,objects:[]}, mousedown:{val:false,x:false,y:false,objects:[]}, drag:{object:false,x:0,y:0}, gCO: 'source-over', redraw:1 } canvas.toDataURL=function(){return canvas.cnv.toDataURL.apply(canvas.cnv,arguments);} canvas.layers=[]; canvas.interval=0; jCanvaScript.layer(idCanvas+'Layer_0').canvas(idCanvas); canvas.recalculateOffset = function() { var offset=getOffset(this.cnv); this.optns.x=offset.left+(parseInt(this.cnv.style.borderTopWidth)||0); this.optns.y=offset.top+(parseInt(this.cnv.style.borderLeftWidth)||0); return this; } canvas.start=function(isAnimated) { lastCanvas=this.optns.number; if(isAnimated) { if(this.interval)return this; this.isAnimated=isAnimated; this.recalculateOffset(); var canvas=canvases[this.optns.number], optns=canvas.optns; this.cnv.onclick=function(e){ mouseEvent(e,'click',optns); } this.cnv.ondblclick=function(e){ mouseEvent(e,'dblclick',optns); var tmp=optns.mousemove.val; optns.mousemove.val=true; setTimeout(function(){optns.mousemove.val=tmp;},3000); } this.cnv.onmousedown=function(e){ mouseEvent(e,'mousedown',optns); } this.cnv.onmouseup=function(e){ mouseEvent(e,'mouseup',optns); } this.cnv.onkeyup=function(e){ keyEvent(e,'keyUp',optns); } this.cnv.onkeydown=function(e) { keyEvent(e,'keyDown',optns); } this.cnv.onkeypress=function(e) { keyEvent(e,'keyPress',optns); } this.cnv.onmouseout=this.cnv.onmousemove=function(e) { mouseEvent(e,'mousemove',optns); }; optns.timeLast=new Date(); this.interval=requestAnimFrame(function(time){ canvas.interval=canvas.interval||1; canvas.frame(time);}, this.cnv); } else return this.frame(); return this; } canvas.pause=function() { cancelRequestAnimFrame(this.interval); this.interval=0; return this; } canvas.restart = function() { return this.pause().start(true); } canvas.del=function() { cancelRequestAnimFrame(this.interval); this.layers=[]; canvases.splice(this.optns.number,1); for(var i=0;i<canvases.length;i++) { var canvas=canvases[i], layers=canvas.layers, limitL=layers.length; canvas.optns.number=i; for(var j=0;j<limitL;j++) { var layer=layers[j]; layer.optns.canvas.number=i; setLayerAndCanvasToArray(layer.objs,layer.optns.id,layer.optns.number,canvas.optns.id,canvas.optns.number); setLayerAndCanvasToArray(layer.grdntsnptrns,layer.optns.id,layer.optns.number,canvas.optns.id,canvas.optns.number); } } if(this.cnv.parentNode)this.cnv.parentNode.removeChild(this.cnv); lastCanvas=0; return false; } canvas.clear=function() { cancelRequestAnimFrame(this.interval); this.interval=0; this.layers=[]; jCanvaScript.layer(this.optns.id+'Layer_0').canvas(this.optns.id); this.optns.ctx.clearRect(0,0,this.optns.width,this.optns.height); this.optns.redraw++; return this; } canvas.frame=function(time) { var optns=this.optns,thisCanvas=this; time=time||(new Date()); optns.timeDiff=time-optns.timeLast; optns.timeLast=time; if(this.interval) { this.interval=requestAnimFrame(function(time){thisCanvas.frame(time);},thisCanvas.cnv); this.interval=this.interval||1; } if(!optns.redraw)return this; optns.redraw--; optns.ctx.clearRect(0,0,optns.width,optns.height); if(this.layers.length==0)return this; limit=this.layers.length; if(optns.anyLayerLevelChanged) limit=levelChanger(this.layers); if(optns.anyLayerDeleted) limit=objDeleter(this.layers); if(optns.anyLayerLevelChanged || optns.anyLayerDeleted) { optns.anyLayerLevelChanged=optns.anyLayerDeleted=false; for(var i=0;i<limit;i++) { var layer=this.layers[i],layerOptns=layer.optns; setLayerAndCanvasToArray(layer.objs,layerOptns.id,layerOptns.number,this.optns.id,this.optns.number); setLayerAndCanvasToArray(layer.grdntsnptrns,layerOptns.id,layerOptns.number,idCanvas,this.optns.number); } } for(i=0;i<limit;i++) { var object=this.layers[i]; if(typeof (object.draw)=='function') if(object.beforeDraw(optns)) { if(typeof (object.draw)=='function') { object.draw(optns); object.afterDraw(optns); } } } var mm=optns.mousemove; var mouseDown=optns.mousedown; var mouseUp=optns.mouseup; var click=this.optns.click; var dblClick=this.optns.dblclick; if(mm.x!=false) { if(optns.drag.object!=false) { var drag=optns.drag, dobject=drag.object; dobject.translate(mm.x-drag.x,mm.y-drag.y); drag.x=mm.x; drag.y=mm.y; if(drag.drag)drag.drag.call(dobject,{x:mm.x,y:mm.y}); } var point = this.optns.point||{}; point.event=mm.event; if(mm.object!=false) { var mousemoveObject=mm.object, mousemoveLayer = objectLayer(mousemoveObject); if(underMouse===mousemoveObject) { if(typeof mousemoveObject.onmousemove === 'function'){ mousemoveObject.onmousemove(point); } if(mousemoveLayer === underMouseLayer){ if(typeof mousemoveLayer.onmousemove === 'function'){ mousemoveLayer.onmousemove(point); } } else { if(underMouseLayer){ if(typeof underMouseLayer.onmouseout === 'function'){ underMouseLayer.onmouseout(point); } } if(typeof mousemoveLayer.onmouseover === 'function'){ mousemoveLayer.onmouseover(point); } underMouseLayer = mousemoveLayer; } } else { if(underMouse){ if(typeof underMouse.onmouseout === 'function'){ underMouse.onmouseout(point); } } if(typeof mousemoveObject.onmouseover === 'function'){ mousemoveObject.onmouseover(point); } underMouse = mousemoveObject; } } else { if(underMouse) { if(typeof underMouse.onmouseout=='function') { underMouse.onmouseout(point); } underMouse=false; } if(underMouseLayer) { if(typeof underMouseLayer.onmouseout=='function') { underMouseLayer.onmouseout(point); } underMouseLayer=false; } } optns.mousemove.object=false; } if(mouseDown.objects.length) { var mdObjectsLength = mouseDown.objects.length - 1; mdCicle: for(i=mdObjectsLength;i>-1;i--) { var mouseDownObjects=[mouseDown.objects[i],objectLayer(mouseDown.objects[i])], mdObject; for(var j=0;j<2;j++) { mdObject=mouseDownObjects[j]; if(mdObject.optns.drag.val==true && mdObject.optns.drag.disabled==false && i == mdObjectsLength) { drag=optns.drag; dobject=drag.object=mdObject.optns.drag.object.visible(true); drag.drag=mdObject.optns.drag.drag; drag.init=mdObject; var initoptns=drag.init.optns; if(initoptns.drag.params!==undefined)dobject.animate(initoptns.drag.params); drag.x=drag.startX=mouseDown.x; drag.y=drag.startY=mouseDown.y; if(dobject!=drag.init && initoptns.drag.type!='clone') { point=transformPoint(mouseDown.x,mouseDown.y,dobject.matrix()); dobject.translate(point.x-dobject._x,point.y-dobject._y); } dobject.translate(initoptns.drag.shiftX,initoptns.drag.shiftY); if(typeof initoptns.drag.start=='function') initoptns.drag.start.call(dobject,{x:mouseDown.x,y:mouseDown.y}); } if(typeof mdObject.onmousedown=='function') if(mdObject.onmousedown({x:mouseDown.x,y:mouseDown.y,event:mouseDown.event})===false) break mdCicle; } } mouseDown.objects=[]; } if(mouseUp.objects.length) { muCicle: for(i=mouseUp.objects.length-1;i>-1;i--) { var mouseUpObjects=[mouseUp.objects[i],objectLayer(mouseUp.objects[i])],muObject; for(j=0;j<2;j++) { muObject=mouseUpObjects[j]; if(stopDrag(muObject, mouseUp, optns))click.objects=[]; if(typeof muObject.onmouseup=='function') if(muObject.onmouseup({x:mouseUp.x,y:mouseUp.y,event:mouseUp.event})===false) break muCicle; } } this.optns.drag={object:false,x:0,y:0}; mouseUp.objects=[]; } if(click.objects.length) { cCicle: for(i=click.objects.length-1;i>-1;i--) { var mouseClickObjects=[click.objects[i],objectLayer(click.objects[i])], clickObject; for(j=0;j<2;j++) { clickObject = mouseClickObjects[j]; stopDrag(clickObject, click, optns); if(typeof clickObject.onclick == 'function') if(clickObject.onclick({x:click.x,y:click.y,event:click.event})===false) break cCicle; } } this.optns.drag={object:false,x:0,y:0}; click.objects=[]; } if(dblClick.objects.length) { dcCicle: for(i=dblClick.objects.length-1;i>-1;i--) { var mouseDblClickObjects=[dblClick.objects[i],objectLayer(dblClick.objects[i])]; for(j=0;j<2;j++) { if(typeof mouseDblClickObjects[j].ondblclick == 'function') if(mouseDblClickObjects[j].ondblclick({x:dblClick.x,y:dblClick.y, event:dblClick.event})===false) break dcCicle; } } dblClick.objects=[]; } optns.keyUp.val=optns.keyDown.val=optns.keyPress.val=click.x=dblClick.x=mouseUp.x=mouseDown.x=mm.x=false; return this; } return canvas; } function stopDrag(object, event, optns){ var drag=optns.drag; if(optns.drag.init && optns.drag.object) { if(object.optns.drop.val==true) { if(drag.init==drag.object) drag.init.visible(true); if(typeof object.optns.drop.fn=='function') object.optns.drop.fn.call(object,drag.init); } else { drag.object.visible(false); drag.init.visible(true); drag.init.optns.translateMatrix[0][2]=drag.object.optns.translateMatrix[0][2]; drag.init.optns.translateMatrix[1][2]=drag.object.optns.translateMatrix[1][2]; changeMatrix(drag.init); if(drag.object!=drag.init)drag.object.visible(false); if(typeof drag.init.optns.drag.stop=='function') drag.init.optns.drag.stop.call(drag.init,{x:event.x,y:event.y}); } return (drag.x!=drag.startX || drag.y!==drag.startY) } return false; } jCanvaScript.layer=function(idLayer) { if(idLayer===undefined)return canvases[0].layers[0]; for(var i=0;i<canvases.length;i++) { var layersArray=canvases[i].layers; for (var j=0;j<layersArray.length;j++) if(layersArray[j].optns.id==idLayer) return layersArray[j]; } return layers(idLayer); } window.jCanvaScript = window.jc = jCanvaScript; })(window, undefined);
实例
jCanvaScript使用心得1(—常用图绘制方法)
绘制圆形
第一种写法: circle(x, y, radius, [color], [fill]); x、y轴圆心坐标,半径,颜色,是否填充(默认为false||0不填充)如: jc.circle(100,120,50,'rgba(255,0,0,0.5)',true);
第二种写法1 circle(object parameters); 将对象作为参数,如: jc.circle({x:100,y:120,radius:50,color:'#ff0000',fill:1});
绘制矩形
rect(x, y, width, height, [color], [fill]); x、y轴左上角坐标,宽高,颜色,是否填充(默认为false||0不填充)如: jc.rect(80,100,120,50,'rgba(255,156,135,0.5)',1);
绘制弧线
arc(x, y, radius, startAngle, endAngle, [anticlockwise], [color], [fill]); x、y轴圆心坐标,半径,起始结束角度,方向(默认为true||1逆时针),颜色,是否填充(默认为false||0不填充)如: jc.arc(60,100,60,90,180,1,'rgb(25,99,253)',0);
绘制路径
line(points, [color], [fill]) 用多个[X,Y]设置路径的点,颜色,是否填充(默认为false||0不填充)如: jc.line([[60,20],[75,132],[220,60]],'#ff5587');
绘制二次曲线,数组的点包含数组(x,y,x控制点,控制点y),用于创建曲线应至少两个数组。
qCurve(points, [color], [fill]) 用多个[x,y,x of control point,y of control point]设置路径的点,颜色,是否填充(默认为false||0不填充)如: var arr=[]; arr[0]=[40,30,30,40]; arr[1]=[30,40,40,30]; arr[2]=[30,180,180,30]; arr[3]=[40,190,190,40]; arr[4]=[180,190,190,180]; arr[5]=[190,180,180,190]; arr[6]=[190,40,40,190]; arr[7]=[180,30,30,180]; jc.qCurve(arr,'#ffbbcc',true);
绘制贝塞尔曲线绘制贝塞尔曲线,数组的点包含数组(x,y,x控制点1,y控制点1,x控制点2,y控制点2]。用于创建曲线应至少两个数组。
bCurve(points, [color], [fill]) 用多个 [x, y, x of control point 1, y of control point 1, x of control point 2, y of control point 2]设置路径的点,颜色,是否填充(默认为false||0不填充)如: var arr=[]; arr[0]=[40,30,30,40,40,30]; arr[1]=[130,140,40,130,130,40]; arr[2]=[30,180,180,30,30,180]; jc.bCurve(arr,true);
绘制渐变创建一个新的空白jCanvaScript ImageData对象与指定的尺寸。通过循环改变setPixel里面颜色的方式绘制渐变
var imgData=jc.imageData(100,100); //设置渐变区域的大小 for(var i=0;i<100;i++){ for(var j=0;j<100;j++){ imgData.setPixel(i,j,'rgba('+i+','+j+','+(i+j)+','+(i/100)+')'); //绘制像素点i,j为像素点坐标 } } imgData.putData(0,0); //设置渐变区域的位置
绘制图像
image(img, x, y, width, height, sX, sY, sWidth, sHeight); 图像对象,x、y轴坐标,图像宽高,从图像X、Y位置选择宽高的图像,如: var img=new Image(); //创建图像对象 img.src="logo.png"; //设置图像地址 img.onload=function(){ //加载图片(canvas绘制图像需要在图片加载结束后) jc.start("can1"); jc.image(img,0,0); jc.rect(50, 50, 24, 24, '#FF0000'); jc.image(img,140,140,48,48,50,50,24,24); //将rect所选区域放大后绘制 jc.start("can1");}
绘制文字
text(text, x, y, [maxWidth], [color], [fill]); 文字字符串,x、y轴坐标,文字显示最大宽度(如果超出会整体压缩文字),颜色,是否填充(默认为true||1不填充)如: jc.text("Colored stroked text",80,140,80,'rgb(255,0,0)', 0);
--------------------------------------------------------------分割线--------------------------------------------------------
canvas 公式
// 把角度转换为弧度 function angleToRadian( angle ) { return Math.PI / 180 * angle; }
## 角度旋转 dx = mouse.x - object.x; dy = mouse.y - object.y; object.rotation = Math.atan2(dy,dx)*180/Math.PI ## 平滑运动 value = center + Math.sin(angle)*range; angle += speed; ## 正圆运动 x_position = centerX + Math.sin(angle)*radius; y_position = centerY + Math.cos(angle)*radius; angle += speed; ## 椭圆运动 x_position = centerX + Math.cos(angle)*radiusX; y_position = centerY + Math.sin(angle)*radiusY; angle += speed; ##两点间距离 dx = x2 - x1; dy = y2 - y1; dist = Math.sqrt(dx*dx + dy*dy);
canvas文字居中
context.textAlign = 'center'; context.textBaseline = 'middle'; context.strokeText(n.toFixed(0) + '%', centerX, centerY);
//计算两点间的中点: function middle(start,end){ return [(start.x+end.x)/2, (start.y+end.y)/2]; } //计算两点间的角度: function angle(start,end){ var diff_x = end.x - start.x, diff_y = end.y - start.y; return 360*Math.atan(diff_y/diff_x)/(2*Math.PI); } //注意:角度的计算方式要在地图上使用,需要先转换成地理坐标 function angleFn(start,end,map) { var p_start = map.lngLatToContainer(new AMap.LngLat(start[0],start[1])); var p_end = map.lngLatToContainer(new AMap.LngLat(end[0],end[1])); var diff_x = p_end.x - p_start.x, diff_y = p_end.y - p_start.y; return 360*Math.atan(diff_y/diff_x)/(2*Math.PI); }
Canvas
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div> <h2>绘制圆形</h2> <canvas id="canvas_1" width="1000" height="500" style="box-shadow: 0px 0px 20px black;"> 当前浏览器不支持 canvas </canvas> </div> </body> <script type="text/javascript"> /* 该方法负责绘制圆角矩形 x1 , y2 : 圆角矩形左上角的坐标 width,height:控制圆角矩形的宽度和高度 radius:控制圆角矩形的四个圆角的半径 */ function creatRoundRect(ctx, x1, y1, width, height, radius){ // 移动到左上角的开始点 ctx.moveTo(x1 + radius, y1); // 添加一条连接开始点到右上角的线段 ctx.lineTo(x1 + width - radius, y1); // 添加右上角的一段圆弧 ctx.arcTo(x1 + width, y1, x1 + width, y1 + radius, radius); // 添加一条连接到右下角的线段 ctx.lineTo(x1 + width, y1 + height - radius); // 添加右下角的一段圆弧 ctx.arcTo(x1 + width, y1 + height, x1 + width - radius, y1 + height, radius); // 添加一条由右下角连接到左下角的线段 ctx.lineTo(x1 + radius, y1 + height); // 添加左下的圆弧 ctx.arcTo(x1, y1 + height, x1, y1 + height - radius,radius); // 添加一条由左下角连接到左上角的线段 ctx.lineTo(x1, y1 + radius); // 添加一段圆弧 ctx.arcTo(x1, y1, x1 + radius, y1, radius); ctx.closePath(); } // 获取 canvas 元素对应的 DOM 对象 var canvas_1 = document.getElementById("canvas_1"); // 获取在 canvas 上绘图的 canvasRenderingContent2D 对象 var ctx = canvas_1.getContext("2d"); ctx.lineWidth = 3; creatRoundRect(ctx, 30, 30, 200, 100, 20); ctx.stroke(); </script> </html> --------------------- 作者:MR_LP 来源:CSDN 原文:https://blog.csdn.net/MR_LP/article/details/51919800?utm_source=copy 版权声明:本文为博主原创文章,转载请附上博文链接!