Rectangular Gradient with HTML5 Canvas Element - html

How can I draw a rectangle with a gradient effect like the one pictured below using the HTML5 canvas element?
Edit: Thanks for all the feedback. Yes, I have already tried many methods. For example, can I use the createRadialGradient method as #Loktar suggests? Here is some sample code:
<html>
<head>
<title>test</title>
<script type="application/x-javascript">
function draw() {
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
var grad1 = ctx.createRadialGradient(50, 50, 0, 50, 50, 50);
grad1.addColorStop(0, 'rgba(255, 252, 0, 1)');
grad1.addColorStop(1, 'rgba(68, 205, 37, 1)');
ctx.fillStyle = grad1;
ctx.fillRect(0, 0, 100, 100);
}
</script>
</head>
<body onload="draw();">
<div>
<canvas id="canvas" width="100" height="100"></canvas>
</div>
</body>
</html>
But the result is not quite what I want:
This should be done easily with a method like PathGradientBrush provided by GDI+.
I'm not sure is it possible with the HTML5 canvas element.

You could try to use a combination of linear gradient and clipping. Demo. Code:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var outerColor = 'rgba(68,205,37,1)';
var innerColor = 'rgba(255,252,0,1)';
var w = 200;
var h = 50;
canvas.width = w;
canvas.height = h;
function gradient(dir) {
var grad = ctx.createLinearGradient(dir[0], dir[1], dir[2], dir[3]);
grad.addColorStop(0, outerColor);
grad.addColorStop(0.5, innerColor);
grad.addColorStop(1.0, outerColor);
return grad;
}
// idea: render background gradient and a clipped "bow"
function background() {
ctx.fillStyle = gradient([0, 0, 0, h]);
ctx.fillRect(0, 0, w, h);
}
function bow() {
ctx.save();
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(w, h);
ctx.lineTo(w, 0);
ctx.lineTo(0, h);
ctx.clip();
ctx.fillStyle = gradient([0, 0, w, 0]);
ctx.fillRect(0, 0, w, h);
ctx.restore();
}
background();
bow();

Related

HTML canvas: How to achieve dropshadow on clipped object?

I am trying to draw a dropshadow on a clipped image.
function drawCircle(ctx,w,h) {
ctx.beginPath();
ctx.ellipse(w/2, h/2, w/2, h/2, 0, 2 * Math.PI, false);
//ctx.fill(); // This helps, but not suitable for transparent images!
}
const canvas = document.getElementById('c');
const ctx = canvas.getContext('2d');
const img = new Image();
img.onload = () => {
// Draw ellipse & clip (removing these 2 lines makes the dropshadow appear)
drawCircle(ctx, img.width,img.height);
ctx.clip();
ctx.shadowOffsetX = 4;
ctx.shadowOffsetY = 4;
ctx.shadowBlur = 4;
ctx.shadowColor = '#000';
ctx.clip();
ctx.drawImage(img, 0, 0);
}
img.src = 'https://i.imgur.com/NdrmFsr.jpg';
Without clipping, the image on the canvas has a very visible drop shadow.
With clipping applied, the drop shadow is not visible.
What do I need to change to make the drop shadow visible on a clipped image?
Fiddle is here: https://jsfiddle.net/av01d/xdemLs2u/
Using the css property filter
filter: drop-shadow(10px 6px 3px rgba(50, 50, 0, 1));
https://jsfiddle.net/nj2rpxz6/
Here is the mozzila doc about the drop-shadow() CSS function
Edit :
Here is how you can add css with Javascript :
const canvas = document.getElementById('c');
canvas.style.filter = "drop-shadow(10px 6px 3px rgba(50, 50, 0, 1))"
I found a solution. Draw the clipped object on a temporary canvas, then draw that canvas with shadow applied to the main canvas.
function drawCircle(ctx,w,h) {
ctx.beginPath();
ctx.ellipse(w/2, h/2, w/2, h/2, 0, 2 * Math.PI, false);
}
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
var img = new Image();
img.onload = () => {
ctx.save();
drawCircle(ctx, img.width,img.height);
ctx.clip();
ctx.drawImage(img, 0, 0);
ctx.restore();
const canvas2 = document.createElement('canvas'), ctx2 = canvas2.getContext('2d');
canvas2.width = canvas.width; canvas2.height = canvas.height;
ctx2.shadowOffsetX = 4;
ctx2.shadowOffsetY = 4;
ctx2.shadowBlur = 4;
ctx2.shadowColor = '#000';
ctx2.drawImage(canvas,0,0);
//ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.drawImage(canvas2,0,0);
}
img.src = 'https://i.imgur.com/NdrmFsr.jpg';

Create pattern with canvas

I would like to create a pettern with canvas. The Picture which should be used should also be gernerated first. I already did something like this with this code:
document.addEventListener('DOMContentLoaded', function () {
async function draw() {
var canvas = document.getElementById('canvas1')
var ctx = canvas.getContext("2d");
var canvas = ctx.createImageData(500, 300);
ctx.fillStyle = "#7289DA";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Select the color of the stroke
ctx.strokeStyle = '#74037b';
// Draw a rectangle with the dimensions of the entire canvas
ctx.strokeRect(0, 0, canvas.width, canvas.height);
ctx.font = 'bold 70px sans-serif';
// Select the style that will be used to fill the text in
ctx.save();
ctx.rotate(1.7*Math.PI);
ctx.fillStyle = '#23272A';
ctx.fillText('Text', -70, 300);
ctx.restore();
// Actually fill the text with a solid color
}
draw();
});
<canvas id="canvas" width="1500" height="900">Beispiel für eine Kachelung eines Musters in Canvas.</canvas>
Now I want to create some kind of grid with it, it should look like this
How can I do that?
The best way would be using two for loops to go over the x and y values! You can surround the part that draws text with these loops and use the changing x and y values instead of hard-coded ones.
async function draw() {
var canvas = document.getElementById('canvas1')
var ctx = canvas.getContext("2d");
var canvas = ctx.createImageData(500, 300);
ctx.fillStyle = "#7289DA";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Select the color of the stroke
ctx.strokeStyle = '#74037b';
// Draw a rectangle with the dimensions of the entire canvas
ctx.strokeRect(0, 0, canvas.width, canvas.height);
ctx.font = 'bold 70px sans-serif';
ctx.fillStyle = '#23272A';
// Select the style that will be used to fill the text in
for (var x = 0; x < canvas.width; x += 100 ) { // 100 is the width
for (var y = 0; y < canvas.height; y += 70) { // 70 is the height
ctx.save();
ctx.translate(x, y); // offset the text
ctx.rotate(1.7*Math.PI);
ctx.fillText('Text', -70, 300);
ctx.restore();
// Actually fill the text with a solid color
}
}
}
The reason ctx.translate(x, y) is used instead of ctx.fillText('Text', x - 70, y + 300) is because using fillText would move the grid at an angle instead of just rotating the letters.

Canvas, animated text rotation

I want to have a animated canvas rotation of a word, while another word on the canvas does not move. But somehow both stand still. What do I have to change?
[link]http://jsfiddle.net/2dszD/8/
var canvas;
var ctx;
var canvasWidth;
var canvasHeight;
var interval = 10;
function init(){
canvas = document.getElementById("canvas");
ctx = canvas.getContext('2d');
canvasWidth = canvas.width;
canvasHeight = canvas.height;
setInterval(redraw, interval);
}
init();
function redraw() {
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
ctx.translate( (200 ), (150 ) );
ctx.rotate( 1*Math.PI/180 );
ctx.fillStyle = '#f00';
ctx.font = '40px san-serif';
ctx.textBaseline = 'top';
ctx.fillText("Hello rotated", 0, 0);
ctx.rotate(-( 1*Math.PI/180 ));
ctx.translate( -(200), -(150) );
ctx.fillStyle = '#f00';
ctx.font = '40px san-serif';
ctx.textBaseline = 'top';
ctx.fillText("Hello still", 0, 0);
}
Actually, your text is rotated by a tiny 1.0 degree.
1*Math.PI/180 represents 1 tiny degree of rotation
So this would be a more noticeable 5 degrees:
ctx.rotate( 5.0 * Math.PI/180 );
A few coding glitches:
You need to increment the rotation angle so your text actually animates
angleInDegrees+=5;
ctx.rotate( angleInDegrees * Math.PI/180 );
setInterval requires a full function as an argument, not just a function name, like this:
setInterval( function(){redraw();}, interval);
And here’s easier way to handle translate/rotate
Instead of un-translating and un-rotating like this:
ctx.translate( (200 ), (150 ) );
ctx.rotate( 1*Math.PI/180 );
// draw stuff here
ctx.rotate(-( 1*Math.PI/180 ));
ctx.translate( -(200), -(150) );
You can instead context.save() and context.restore() which is cleaner and doesn’t require un-doing:
// save the canvas context—including its un-translated and un-rotated setting
ctx.save();
ctx.translate(200,150);
ctx.rotate( angleInDegrees * Math.PI/180 );
// draw stuff here
// after restore() the canvas is back to its starting position before save()
ctx.restore();
Here’s code and a Fiddle: http://jsfiddle.net/m1erickson/5XTcn/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvasWidth;
var canvasHeight;
var interval = 350;
var angleInDegrees=0;
function init(){
canvas = document.getElementById("canvas");
ctx = canvas.getContext('2d');
canvasWidth = canvas.width;
canvasHeight = canvas.height;
setInterval( function(){redraw();}, interval);
}
init();
function redraw() {
angleInDegrees+=5;
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
ctx.beginPath();
ctx.rect(200,150,5,5);
ctx.fill();
ctx.save();
ctx.translate(200,150);
ctx.rotate( angleInDegrees * Math.PI/180 );
ctx.fillStyle = '#f00';
ctx.font = '40px san-serif';
ctx.textBaseline = 'top';
ctx.fillText("Hello rotated", 0, 0);
ctx.restore();
ctx.fillStyle = '#f00';
ctx.font = '40px san-serif';
ctx.textBaseline = 'top';
ctx.fillText("Hello still", 0, 0);
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=500 height=300></canvas>
</body>
</html>

Canvas transparency mask effect reset

I'm trying to overlay a canvas on a page in an attempt to make it look like it has been frosted over and then use mousemove to clear it away, following this post:
http://www.stevecalderon.com/2012/03/html5-canvas-tricks-transparency-mask-for-eraser-effect.html
I have created a jsfiddle - http://jsfiddle.net/ZWsG6/2/
var canvas = "";
var ctx = "";
function frost2(){
var int=self.setInterval(function(){clock()},1000);
canvas = document.createElement("canvas");
canvas.width = window.innerWidth;
canvas.height= window.innerHeight;
canvas.style.position = "absolute";
canvas.style.top = "0px";
canvas.style.left = "0px";
var objTo = document.getElementById("fltouch");
objTo.appendChild(canvas);
ctx = canvas.getContext('2d');
ctx.globalAlpha = 0.95;
ctx.fillStyle = "rgb(0, 255, 255)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.globalCompositeOperation = 'destination-out';
function drawPoint(pointX,pointY){
///scrape
var grd = ctx.createLinearGradient(pointX - 75,pointY-5,pointX + 75,pointY + 5)
grd.addColorStop(0, "transparent");
grd.addColorStop(0.3, "rgba(255,255,255,.6)");
grd.addColorStop(0.7, "rgba(255,255,255,.6)");
grd.addColorStop(1, "transparent");
ctx.fillStyle = grd;
ctx.fillRect(pointX - 75,pointY,400,30);
}
canvas.addEventListener('mousemove',function(e){
e.preventDefault();
drawPoint(e.pageX,e.pageY);
},false);
}
function clock(){
ctx.globalAlpha = 0.95;
ctx.fillStyle = "rgb(0, 255, 255)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.globalCompositeOperation = 'destination-out';
}
I've added a function clock() to run every second and refill the canvas with the colour so that it needs to be cleared again but it doesn't work, only remove the fill altogether.
Can anyone please tell how to reset the canvas to be filled with colour again? If it could be done slowly to look sorta like it is freezing over again that would be a bonus.
You need to set globalCompositeOperation back to default source-over value before refilling a canvas:
function clock() {
ctx.globalCompositeOperation = 'source-over';
ctx.globalAlpha = 0.95;
ctx.fillStyle = "rgb(0, 255, 255)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.globalCompositeOperation = 'destination-out';
}
http://jsfiddle.net/VqCbv/1/

Draw rectancle with border without filling in html5

I am trying to create a grid in the canvas as below
var canvas = $("#canvas");
var ctx = canvas.get(0).getContext("2d");
ctx.strokeStyle = "rgb(0, 0, 0)";
for(x=0;x<=300;x++){
for(y=0;y<=300;y++){
ctx.strokeRect(x, y, 20, 20);
}
}
but it just fills the HTML5 canvas instead of drawing squares with border. Can someone enlighten me on what I'm doing wrong here?
I re-wrote it like this
var canvas = $("#myCanvas");
var context = canvas.get(0).getContext("2d");
context.strokeStyle = "rgb(255, 0, 0)";
for(x=0; x<5; x++){
for(y=0; y<5; y++){
context.strokeRect(y*20, x*20, 20, 20);
}
}