I'm using JQueryKnob and trying to add segments to the radial. I'm not well versed in Canvas drawing, so that didn't seem like the best road to take - what I really need to do is just overlay a mask image on the drawn Knob canvas element. I've tried variations of this and it doesn't seem to work (I'm guessing the mask can't apply to canvases?)
I started to dabble with trying to just draw alpha'd lines in the JQueryKnob draw method, but didn't really have any luck with that either.
Any ideas? I'm pretty lost here
You're on the right track...just draw your masked image inside the draw method of your knob.
$(".knob").knob({
draw : function () {
var ctx=this.g;
var x=this.xy;
var y=this.xy;
var r=this.radius;
var iw=img.width;
var ih=img.height;
ctx.save();
ctx.beginPath();
ctx.arc(x,y,r,0,Math.PI*2);
ctx.clip();
ctx.drawImage( img, 0,0,iw,ih, x-iw/2,y-ih/2,iw,ih );
ctx.restore();
}
});
Here's example code and a Demo: https://jsfiddle.net/m1erickson/g8rx58hh/
Related
I am searching for a solution to draw a border around all shapes on an Image. I have already tried this solution Draw border around nontransparent part of image on canvas but this doesnt work for me.
Imagine this png
the solution I am looking for should look like this
is there any libary/solution?
Thank you
If you're drawing the all the shapes using ctx.fill(), you can just call ctx.stroke() before each call to ctx.fill(). This will result in a line of width ctx.lineWidth/2, since half of the line will be covered by the shape itself. However, his won't work for other methods such as ctx.drawImage() or ctx.putImageData(). Please specify how exactly you're drawing these shapes to the canvas to receive some more detailed help.
Edit: I think you can use the solution you already mentioned, you just need to make the non-black part of your image transparent. You can do this by editing the the imageData of the canvas:
var ctx = canvas.getContext("2d");
var imageData = ctx.getImageData(0,0,canvas.width,canvas.height);
for (let i=0;i<imageData.data.length;i+=4){
if (shouldBeTransparent(imageData.data[i],imageData.data[i+1],imageData.data[i+2]){
imageData.data[i+3] = 0;
}
}
ctx.putImageData(imageData,0,0);
function shouldBeTransparent(r,g,b){
return r!=0||g!=0||b!=0;
}
This will make all pixels that are not entirely black transparent, so you can continue with the method you already mentioned.
I am creating a game, I need to achieve a perfect canvas line on HTML5 under different types of screen resolutions and zooms.
To easily understand I am talking about, simply paste the two different codes into an HTML file(not jsFiddle, as it is too small to notice):
With fabric.js:
<canvas id = "c" width = "600" height = "300"></canvas>
<script src = "https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<script> var c=document.getElementById("c");
var context=c.getContext("2d");
new fabric.Canvas('c', { selection: false });
context.moveTo(0, 0);
context.lineTo(0, 300);
context.stroke();
</script>
Without fabric.js:
<canvas id = "c" width = "600" height = "300"></canvas>
<script> var c=document.getElementById("c");
var context=c.getContext("2d");
context.moveTo(0, 0);
context.lineTo(0, 300);
context.stroke();
</script>
Now as you can see, fabric.js removes the blurriness that you get under different kind of browser zooms(Mouse wheel) once the page loads.
I have two problems with it though:
1) Once you click on the canvas the line is gone
2) It's a big framework/library, and I only need it to draw lines(Maybe not if it can achieve the same thing with PNG images)
So, is there a way to achieve the same sharpness result with a clean, short javascript code, without using fabric.js?
If not, how can I fix the clicking problem?
Thanks.
All lines drawn on the canvas are automatically given anti-aliasing to lessen the visual effect of "jaggies". This anti-aliasing also makes the line appear blurry.
If you ONLY are drawing horizontal and vertical lines you can make them crisp:
Before drawing the lines, context.translate(0.50,0.50),
Draw the lines using only integer coordinates,
After drawing the lines, context.translate(-0.50,-0.50),
If you are drawing non-horizontal and non-vertical lines, then you can use Bresenhan's Line Algorithm to draw crisp lines on the canvas by drawing lines pixel-by-pixel. This previous Q&A has example code using Bresenhan's algorithm.
When I run this code it produces the lines "rotating" from 0 degrees to 180, the problem is the previous line does not get cleared (so the ctx.clearRect(0,0,400,200) does not work. In the console log it shows up as running (when I try to debug) but it is not actually clearing it. Does anyone have any idea how to fix this?
var canvas = document.getElementById("radarImage");
var ctx = canvas.getContext("2d");
var angle = 0
function incrementAngle(){
angle++;
if(angle>180){
angle=0;
}
}
function rotateRadar(){
incrementAngle();
ctx.clearRect(0,0,400,200);
ctx.save();
ctx..translate(-200,-200);
ctx.rotate((Math.PI/180)*angle);
ctx.translate(-200,-200);
ctx.moveTo(200,200);
ctx.lineTo(0,200);
ctx.stroke();
ctx.restore;
}
setInterval(rotateRadar,200);
Edit: You should call your updates constantly using request animation frame: http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
If you are open to using a library for working with canvas then easel js is could be a possibility: http://www.createjs.com/easeljs
Another SO user asked a similar question for Easel Js and there are some good answers that may be relavant to you: EaselJS - Rotate a shape around its center
Simply you cant rotate a line cont in canvas, you have to read sin,cos to rotate a line in canvas.
Hope this should help you.JsFiddle
context.clearRect(0,0,400,200);
context.beginPath();
context.moveTo(x,y);
x1=Math.cos(startAngle)*radius+10;
y1=Math.sin(startAngle)*radius+10;
console.log(x1,y1);
context.lineTo(x1,y1);
context.stroke();
So I have a semi-complex canvas drawing someone gave me. It draws an image vertically (i.e., top-down). Let's assume its a stick figure with facial features.
This is done in Javascript and Canvas. i.e.: ctx.beginPath(), ctx.moveTo(x,y), ctx.lineTo(1,1), etc.
I want the stick figure to move towards some point (x,y) and to face that direction while moving toward it. For example, if the x,y is near the bottom right, I want the stick figure to be oriented in a way such that its feet are facing towards the bottom right while it is moving.
The main question is, how would I go about doing this (i.e changing the stickman), knowing that I have a "hardcoded" drawing (in this example, stickman) that has been given to me?
You can render the received image on a separate canvas (doesn't need to be displayed) and use ctx.canvas.toDataURL() to convert it to an image. You could then embed the resulting image in your canvas and apply transforms to it more easily.
I mentioned this in a comment on the question but it sounded like fun, so I implemented a proof of concept.
var canvasObject = function(ctx) {
ctx.beginPath();
ctx.moveTo(0,0);
ctx.arc(30,30,15,0,2*Math.PI);
ctx.fillStyle='red';
ctx.fill();
return ctx;
}
var myCtx = document.querySelector('canvas').getContext('2d');
var objCtx = document.createElement('canvas').getContext('2d');
var renderedObjUrl = canvasObject(objCtx).canvas.toDataURL();
var renderedObj = document.createElement('img');
renderedObj.setAttribute('src', renderedObjUrl);
myCtx.drawImage(renderedObj, 30, 10);
<canvas id="myCanvas" width="600" height="400"></canvas>
Is there a way to use an image as a clipping mask instead of creating a shape like this:
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
// Clip a rectangular area
ctx.rect(50,20,200,120);
ctx.stroke();
ctx.clip();
I have tried to context.drawImage('myimg.png') on top of the context and clip but that did not work.
You can only directly clip using a path.
If you have an image that you wish to clip by, you can probably achieve this by drawing your content in another canvas, and then using globalCompositeOperation combined with drawImage (with the mask) to remove the bits you don't want.
You would then then use .drawImage again (possibly with a different globalCompositeOperation) to merge that clipped image with your original content.
See for example http://www.html5canvastutorials.com/advanced/html5-canvas-global-composite-operations-tutorial/