I was wondering if there is a way to draw an image but give it a colourized effect.
If you consider games, when you want to place a sprite but theres an object in the way, often the object you try to place get a red tint to it to indicate it cannot be placed which is what im trying to achieve.
I currently draw it with an opacity here:
ctx.globalAlpha = 0.5
ctx.drawImage(image,abposx,abposy);
Is this possible to achieve without a library?
You can draw a semitransparent rectangle over top of it. For example:
ctx.fillStyle = 'rgba(255, 0, 0, 0.5)'; // 1/2 opacity red
ctx.fillRect(0, 0, 30, 30); // Draw this over top of your image
Here's a demo.
For isometric images, all you have to do is create the appropriate path. Here's an example of that:
You can clip the overlay to your image by setting the globalCompositeOperation to source-atop:
ctx.globalCompositeOperation = 'source-atop';
ctx.fillStyle = 'rgba(255, 0, 0, 0.5)'; // 1/2 opacity red
ctx.fillRect(0, 0, 30, 30); // Draw this over top of your image
ctx.globalCompositeOperation = 'source-over';
Here's a demo. You may also have to use a shadow canvas if the areas you're trying to draw on also have content, though.
Related
So like I said in the title, I'm trying to make a color picker (with HTML/CSS/JS, if that matters) and I'm basing it off of DuckDuckGo's color picker (seen here).
They use a semi-transparent image overlayed on a div with a solid color. I thought that the image was just a vertical white --> black gradient and a horizontal and vertical opacity gradient. It turns out its more complicated than that.
I downloaded the image they use for their color picker and removed the alpha channel. I've uploaded it here. By the way, it appears they have subtle noise over it, for some reason.
I don't know what equation is used to generate this.
I do know that the alpha channel is equal to 1 - (x * y), but I don't know what algorithm is used to get the rgb channels.
I would also like to generate a similar image for an HSL color picker. I assume its the same algorithm, but scaled vertically by half and mirrored. Is that correct?
I solved it.
Draw a gradient going from solid white on the left to transparent white (rgba(255,255,255,0)) on the right, then drawing another gradient over top that using alpha blending which goes from solid black at the bottom to transparent black at the top.
Example code using the javascript canvas
var ctx = document.getElementByID("canvas").getContext("2d");
var saturationGradient = ctx.createLinearGradient(0, 0, 256, 0);
saturationGradient.addColorStop(0, "rgba(255, 255, 255, 1)"); //white
saturationGradient.addColorStop(1, "rgba(255, 255, 255, 0)"); //white transparent
var valueGradient = ctx.createLinearGradient(0, 0, 0, 256);
valueGradient.addColorStop(0, "rgba(0, 0, 0, 0)"); //transparent
valueGradient.addColorStop(1, "rgba(0, 0, 0, 1)"); //black
ctx.fillStyle = saturationGradient;
ctx.fillRect(0, 0, 256, 256);
ctx.fillStyle = valueGradient;
ctx.fillRect(0, 0, 256, 256);
The reason I couldn't figure it out was because I was using multiply blending instead of alpha blending.
I still haven't figured out a set of gradients for an HSL color picker.
I have the following problem:
I need to transform text on a HTML canvas, e.g. give it a trapezoid shape.
Here's what I tried:
context.beginPath();
context.moveTo(0, 0);
context.lineTo(200, 0);
context.lineTo(100, -100);
context.lineTo(0, -100);
context.closePath();
context.clip();
context.fillText("Hello World", this.x, this.y);
As you might have guessed, the text gets cut off instead of transformed to fit the shape. Below are images of what I am trying to do and what I managed to do.
Any help is appreciated :)
What I managed to do:
What I want to do:
What you can do is get a dummy canvas element in which you put your normal text, then you can apply your own maths to the pixel color values in textCtx.getImageData onto another imageData array that you create, so you can then put that into another canvas with the correct transform with transformedTextCtx.putImageData, and finally draw its canvas onto the original context with ctx.drawImage.
I'm going to assume you know the kind of maths that you want to apply, and if not I suggest you look into skewing and scaling, and find out how you can combine the two.
The mdn resources for the imageData methods are in the "Pixel Manipulation" subsection of the canvas rendering context page: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D#Pixel_manipulation
General Answer: How to transform text
You can transform your text (or anything else) by using canvasContext.setTransform before drawing. You don't need any second canvas.
Examples:
canvasContext.setTransform(1, 0, 0, 1, 0, 0); is the default
canvasContext.setTransform(0.5, 0, 0, 1, 0, 0); reduces width to 50%
canvasContext.setTransform(1, 0, 0, 0.5, 0, 0); reduces height to 50%
Specific Answer:
I couldn't figure this out quickly. I'll leave it up to the next user to figure it out.
I want to use an image like this on canvas:
The user will "paint and fill" the image, but not on top of the outline.
The problem is:
If I put behind the canvas, the paint will cover the outline.
If I put over the canvas the image block canvas interaction.
Can you help me guys?
Use compositing mode "destination-over" to draw behind existing content (from image, vectors etc.). It's necessary that the existing content provide an alpha channel or composition won't work. If there is no alpha-channel you can convert inverse luma / matte (the white) to alpha channel.
// a quick-n-dirty demo
var ctx = c.getContext("2d");
ctx.lineWidth = 10;
ctx.moveTo(100, 0); ctx.lineTo(150, 150); ctx.stroke();
ctx.fillStyle = "#09f";
// KEY: composite mode -
ctx.globalCompositeOperation = "destination-over";
// draw behind the line
c.onmousemove = function(e) {
ctx.fillRect(e.clientX - 10, e.clientY - 10, 20, 20);
};
body {margin:0}
canvas {border:#777 solid 1px}
<canvas id="c"></canvas>
Here is the example of drawImage function. You can draw any preloaded image onto canvas. You can also try to place the <img> overlay in front of the canvas and disable mouse events for it using pointer-events: none CSS property.
i want to set transparency for part of canvas
can I use globalAlpha like for all canvas except rectangle i create in the canvas ?
If you mean how to make a rectangle transparent after you have a bunch of things drawn to the canvas you can do the following:
/// clear a rectangle to make canvas transparent
ctx.globalCompositeOperation = 'destination-out';
/// set alpha using a fill color with transparency
ctx.fillStyle = 'rgba(0,0,0,0.5)';
/// fill rectangle which now will become partly transparent all the way
ctx.fillRect(40, 40, 320, 320);
/// reset composite mode
ctx.globalCompositeOperation = 'source-over';
Live demo here
If this is not what you mean then you need to plan your drawings. As mentioned elsewhere you can set globalAlpha before you draw something, draw it, then set globalAlpha back before you draw the next. Each draw after setting globalAlpha will be drawn with that alpha value (if the fill-style, stroke-style of image alpha uses transparency as well that will be a result of the two alpha values as they are multiplied).
globalCompositeOperation decides how it will be drawn, for example on top of existing content, instead of and so forth (see an overview here).
As I've said in the comments twice, you just have to set the global alpha to what you want, draw what you want with that alpha, then change the global alpha to a new value, then draw what you want in that alpha. That can be done as follows
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = 'rgba(255, 0, 0,1)';
ctx.fillRect(0, 0, 150, 50);
ctx.globalAlpha = 0.2;
ctx.fillRect(150,50,150,50);
Demo
This small code clear old canvas data in interval:
// start interval
ctx.save();
ctx.fillStyle = "rgba(0, 0, 0, 0.2)";
ctx.fillRect(0, 0, ctx.width, ctx.height);
ctx.restore();
//some draw code for new graph
...
//end interval
My work area become black, because I set black as fill color (rgba(0, 0, 0, .2)), but I need a transparent background, not black.
I tried use globalAlpha and imagePutData but I failed.
How I can do this?
I think this will resolve your issue
ctx.fillStyle = "rgba(255, 255, 255, 0.5)";
Using an rgba(0,0,0,.2) fillStyle and fillRect() works for me on both chrome and firefox - it paints a semi-transparent black fill. Check to make sure you're not doing something else that's causing a fully opaque paint of some sort.
try ctx.canvas.width, instead of ctx.width
Has your problem been solved
I encountered this problem while using Windows computer
I used opacity: .99 solved this problem