Rat = function(context){ this.context = context; };
var path = rat.path([ ['moveTo', 10, 10], ['lineTo', 100, 100], ['lineTo', 10, 100], ['closePath'] ], { fillStyle: 'red', strokeStyle: 'green', lineWidth: 4 });
Rat.init = function(cls, arg){ cls.opt = arg[0]; cls.style = arg[1] || {}; cls.context = arg[2]; cls.draw(arg[2].context); };
Rat.Path = function(opt, style, context){ Rat.init(this, arguments); };
Rat.Path.prototype = { draw: function(ctx){ this.process(function(ctx){ if(this.style.fillStyle) ctx.fill(); if(this.style.strokeStyle) ctx.stroke(); }, ctx); }, process: function(callback, ctx){ ctx = ctx || this.context.context; Rat.style(ctx, this.style); ctx.beginPath(); this.opt.forEach(function(func){ ctx[func[0]].apply(ctx, func.slice(1)); }); var result = callback.call(this, ctx); ctx.restore(); return result; } };
isPointIn: function(x,y, ctx){ return this.process(function(ctx){ return ctx.isPointInPath(x, y); }, ctx); }
// , // Rat.notStyle = "translate0rotate0transform0scale".split(0); Rat.style = function(ctx, style){ ctx.save(); style.origin && ctx.translate.apply(ctx, style.origin); style.rotate && ctx.rotate(style.rotate); style.scale && ctx.scale.apply(ctx, style.scale); style.origin && ctx.translate(-style.origin[0], -style.origin[1]); style.translate && ctx.translate.apply(ctx, style.translate); // , origin? style.transform && ctx.transform.apply(ctx, style.transform); Object.keys(style).forEach(function(key){ if(!~Rat.notStyle.indexOf(key)) ctx[key] = style[key]; }); };
!~Rat.notStyle.indexOf(key)
- the same as Rat.notStyle.indexOf(key) != -1
. This is a micro library though.
Rat.prototype = { path : function(opt, style){ return new Rat.Path(opt, style, this); }, };
var path = rat.path([ ['moveTo', 10, 10], ['lineTo', 100, 100], ['lineTo', 10, 100], ['closePath'] ], { fillStyle: 'red', strokeStyle: 'green', lineWidth: 4, rotate: 45 / 180 * Math.PI, origin: [55, 55] });
The picture is cropped because drawn in zero coordinates.
var img = new Image(); img.src = "image.jpg"; img.onload = function(){ rat.image(img); }
Rat.Image = function(opt, style, context){ Rat.init(this, arguments); };
Rat.Image.prototype.draw = function(ctx){ Rat.style(ctx, this.style); if(this.style.crop) ctx.drawImage.apply(ctx, [this.opt, 0, 0].concat(this.style.crop)); else ctx.drawImage(this.opt, 0, 0, this.style.width || this.opt.width, this.style.height || this.opt.height); ctx.restore(); };
Rat.prototype = { ... image : function(opt, style){ return new Rat.Image(opt, style, this); }, };
var text = rat.text("Hello, world!", { fillStyle: 'blue' });
There is also a maxWidth property.
Rat.Text = function(){ Rat.init(this, arguments); };
Rat.Text.prototype.draw = function(ctx){ Rat.style(ctx, this.style); if(this.style.fillStyle) ctx.fillText(this.opt, 0, 0, this.style.maxWidth || 999999999999999); if(this.style.strokeStyle) ctx.strokeText(this.opt, 0, 0, this.style.maxWidth || 9999999999999999); ctx.restore(); };
Rat.Text.prototype.measure = function(){ var ctx = this.context.context; Rat.style(ctx, this.style); var w = ctx.measureText(this.opt).width; ctx.restore(); return w; };
Rat.prototype = { ... image : function(opt, style){ return new Rat.Image(opt, style, this); }, };
Rat.prototype = { ... clear: function(){ var cnv = this.context.canvas; this.context.clearRect(0, 0, cnv.width, cnv.height); } };
Rat.prototype = { ... draw: function(elements){ var ctx = this.context; elements.forEach(function(element){ element.draw(ctx); }); } };
// var path = rat.path([ ['moveTo', 10, 10], ['lineTo', 100, 10], ['lineTo', 100, 40], ['lineTo', 10, 40], ['closePath'] ], { fillStyle: '#eee', strokeStyle: '#aaa', lineWidth: 2 }); // var text = rat.text("Hello, world", { translate: [55, 28], textAlign: 'center', fillStyle: 'black' });
var bounds = ctx.canvas.getBoundingClientRect(); var hover = false; ctx.canvas.addEventListener('mousemove', function(e){ var x = e.clientX - bounds.left, y = e.clientY - bounds.top; if(x > 10 && x < 100 && y > 10 && y < 40){ if(hover) return; hover = true; path.style.fillStyle = '#ccc'; rat.clear(); rat.draw([path, text]); } else if(hover){ hover = false; path.style.fillStyle = '#eee'; rat.clear(); rat.draw([path, text]); } });
// var path = { fill: '#eee', draw: function(){ ctx.moveTo(10, 10); ctx.lineTo(100, 10); ctx.lineTo(100, 40); ctx.lineTo(10, 40); ctx.closePath(); ctx.fillStyle = this.fill; ctx.strokeStyle = '#aaa'; ctx.lineWidth = 2; ctx.fill(); ctx.stroke(); } }; // var text = { draw: function(){ ctx.textAlign = 'center'; ctx.fillStyle = 'black'; ctx.fillText("Hello, world", 55, 28); } }; path.draw(); text.draw(); var bounds = ctx.canvas.getBoundingClientRect(); var hover = false; ctx.canvas.addEventListener('mousemove', function(e){ var x = e.clientX - bounds.left, y = e.clientY - bounds.top; if(x > 10 && x < 100 && y > 10 && y < 40){ if(hover) return; hover = true; path.fill = '#ccc'; ctx.clearRect(0, 0, 800, 400); path.draw(); text.draw(); } else if(hover){ hover = false; path.fill = '#eee'; ctx.clearRect(0, 0, 800, 400); path.draw(); text.draw(); } });
Source: https://habr.com/ru/post/270255/