Opacity to canvas without affecting inner image - javascript

The problem I have is on the image slider. The blue triangule is created using a multiply canvas effect seen here:
http://albertogasparin.it/articles/2011/05/html5-multiply-filter-canvas/
I want the blue triangle to have it's opacity to 0.5, but if I put that on the css (canvas element) it also affects the opacity of the image that's below. Any ideas how to achieve this?
This is my code:
function to_canvas(im,w,h){
var isIE8 = $.browser.msie && +$.browser.version === 8;
var canvas;
var imageBottom;
var im_w = w;
var im_h = h;
var imgData;
var pix;
var pixcount = 0;
var paintrow = 0;
var multiplyColor = [70, 116, 145];
var x_offset = Math.floor(($('#'+im).attr('width') - im_w)/2);
var y_offset = Math.floor(($('#'+im).attr('height') - im_h)/2);
if ( isIE8 ) {
$('<div />' , {
'id' : 'div-'+im,
'class' : 'pseudo_canvas'
}).css({
'width' : im_w,
'height' : im_h
}).insertBefore('#'+im);
$('#'+im).appendTo('#div-'+im).fadeIn();
$('<img>' , {
'src' : '/img/blueborder.png',
'class' : 'blueborder'
}).css({
}).insertBefore('#'+im);
$('#'+im).appendTo('#div-'+im).fadeIn();
}else{
imageBottom = document.getElementById(im);
canvas = document.createElement('canvas');
canvas.width = im_w;
canvas.height = im_h;
imageBottom.parentNode.insertBefore(canvas, imageBottom);
ctx = canvas.getContext('2d');
ctx.drawImage(imageBottom, -x_offset , -y_offset);
imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
pix = imgData.data;
for (var i = 0 ; i < pix.length; i += 4) {
if(pixcount > im_w - (im_h - paintrow) ){
pix[i ] = multiply(multiplyColor[0], pix[i ]);
pix[i+1] = multiply(multiplyColor[1], pix[i+1]);
pix[i+2] = multiply(multiplyColor[2], pix[i+2]);
}
if(pixcount < im_w-1){
pixcount++;
}else{
paintrow++;
pixcount = 0;
}
}
ctx.putImageData(imgData, 0, 0);
/* $('#'+im).remove(); */
}
}
function multiply(topValue, bottomValue){
return topValue * bottomValue / 255;
}
This is how I want the triangle color/opacity (obviously without the opacity of the image on the back):

if u have canvas-
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
context.globalCompositeOperation = "destination-over";
context.fillStyle = "rgba(0, 0, 200, 0.5)";//Change the color combination here
context.fillRect(0, 0, 1000, 1000);

one way would be to use a semi-transparent background instead (e.g. png file)

Related

How do I implement color collision in JavaScript using getImageData?

In my code:
var canvas = document.createElement('canvas');
canvas.width = 1600;
canvas.height = 900;
document.body.appendChild(canvas);
var similarX = 0;
var similarY = 0;
document.addEventListener('mousemove',function(event){
similarX = event.clientX;
similarY = event.clientY;
document.getElementById('body').innerHTML = "x:" + similarX + ", y:" + similarY +", imgData:" + pixelData;
var pixelData = rect.getImageData(60, 60, 1, 1).data;
})
window.addEventListener('load' , start);
var c = canvas.getContext('2d')
var rect = canvas.getContext ('2d')
var circle = canvas.getContext ('2d')
function start() {
c.clearRect(0, 0, 1600, 900);
c.fillStyle = 'green' ;
c.fillRect(similarX - 12, similarY - 50, 20, 20);
rect.fillStyle = 'black';
rect.fillRect(50,50,80,80);
window.requestAnimationFrame(start)
}
document.body.appendChild(canvas);
I want to detect what color are the pixels around the green player square so that if it touches the black box, it is detected by a getImageData() command? I tried reading the other posts, but I couldn't find a way to use them. Is there a solution that can easily be placed inside the code?

How to scale an image for a canvas pattern?

I want to fill a Canvas with an Image and scale it to a certain width beforehand.
I am trying to achieve an effect where an image in the foreground of the canvas can be erased with the mouse to view an image in the background. This is why I need to use a pattern to fill my canvas instead of just using drawImage(). Everything works apart from the scaling of the foreground image. Here is my code for generating the pattern:
var blueprint_background = new Image();
blueprint_background.src = "myfunurl";
blueprint_background.width = window.innerWidth;
blueprint_background.onload = function(){
var pattern = context.createPattern(this, "no-repeat");
context.fillStyle = pattern;
context.fillRect(0, 0, window.innerWidth, 768);
context.fill();
};
This does exactly what it should do, except that the image keeps its original size.
As you see, I want the image to scale to window.innerWidth (which has the value 1920 when logging it).
If needed, I can provide the rest of the code, but since the error is most likely in this snippet, I decided not to post the rest.
EDIT: Here is my full code with the suggested changes. The front ground image now displays over the full width, however the erasing does not work anymore.
JavaScript (Note that I use jQuery instead of $):
jQuery(document).ready(function() {
var cwidth = window.innerWidth;
var cheight = 768;
function createCanvas(parent, width, height) {
var canvas = {};
canvas.node = document.createElement('canvas');
canvas.context = canvas.node.getContext('2d');
canvas.node.width = width || 100;
canvas.node.height = height || 100;
parent.appendChild(canvas.node);
return canvas;
}
function init(canvas, fillColor) {
var ctx = canvas.context;
canvas.isDrawing = true;
jQuery('#canvas').children().css('position:absolute; top: ' + jQuery('#Top_bar').height() + 'px');
// define a custom fillCircle method
ctx.fillCircle = function(x, y, radius, fillColor) {
this.fillStyle = fillColor;
this.beginPath();
this.moveTo(x, y);
this.arc(x, y, radius, 0, Math.PI * 2, false);
this.fill();
};
// bind mouse events
canvas.onmousemove = function(e) {
if (!canvas.isDrawing) {
return;
}
var x = e.pageX - this.offsetLeft;
var y = e.pageY - jQuery('#Top_bar').outerHeight();
var radius = 30;
var fillColor = '#ff0000';
ctx.globalCompositeOperation = 'destination-out';
ctx.fillCircle(x, y, radius, fillColor);
};
}
var container = document.getElementById('canvas');
jQuery('#canvas').css('position:absolute; top: ' + jQuery('#Top_bar').height() + 'px');
var canvas = createCanvas(container, cwidth, cheight);
init(canvas, '#ddd');
var fgimg = document.getElementById("fgimg");
fgimg.width = cwidth;
var context = canvas.node.getContext("2d");
let canvasP = document.getElementById("pattern");
canvasP.width = window.innerWidth;
canvasP.height = 768;
let ctxP = canvasP.getContext("2d");
ctxP.drawImage( fgimg, 0, 0,window.innerWidth,768 );
context.fillStyle = context.createPattern(canvasP,"no-repeat");
context.fillRect(0,0, canvas.width, canvas.height);
});
CSS:
#canvas {
background:url(http://ulmke-web.de/wp-content/uploads/2019/01/Header-6.jpg);
background-repeat: no-repeat;
background-size: cover;
background-position: center center;
width: 100%;
height: 768px;
}
HTML:
<div id="canvas">
<canvas id="pattern">
</div>
<div style="display:none">
<img id="fgimg" src=" http://ulmke-web.de/wp-content/uploads/2019/01/Header-5.jpg">
</div>
I would use two canvases. On the first one you draw your image and you use this canvas as an image to create the pattern. In order to scale the image you scale the size of the first canvas #pattern in my example.
For example you can do this for a 10/10 image:
canvasP.width = 10;
canvasP.height = 10;
ctxP.drawImage( redpoint, 2.5, 2.5 );
or you can do this for a 20/20 image:
canvasP.width = 20;
canvasP.height = 20;
ctxP.drawImage( redpoint, 5, 5,10,10 );
Furthermore, in my example I'm adding a little margin around the image.
let canvasP = document.getElementById("pattern");
if (canvasP && canvasP.getContext) {
let ctxP = canvasP.getContext("2d");
/*canvasP.width = 10;
canvasP.height = 10;
ctxP.drawImage( redpoint, 2.5, 2.5 ); */
canvasP.width = 20;
canvasP.height = 20;
ctxP.drawImage( redpoint, 5, 5,10,10 );
}
let canvas1 = document.getElementById("canvas");
if (canvas1 && canvas1.getContext) {
let ctx1 = canvas1.getContext("2d");
if (ctx1) {
ctx1.fillStyle = ctx1.createPattern(canvasP,"repeat");
ctx1.fillRect(0,0, canvas1.width, canvas1.height);
}
}
canvas{border:1px solid}
<img id="redpoint" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO 9TXL0Y4OHwAAAABJRU5ErkJggg==">
<canvas id="pattern"></canvas>
<canvas id="canvas"></canvas>
I hope it helps.

HTML5 Canvas scaling an image animation

I've created a straight forward linear HTML5 animation but I now want the image to continuously scale bigger then smaller until the end of the canvas' height.
What's the best way to do this?
Here's a JSFIDDLE
window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.oRequestAnimationFrame;
var canvas = document.getElementById('monopoly-piece');
var context = canvas.getContext('2d');
var img = document.createElement("img");
img.src = "images/tophat.png";
img.shadowBlur = 15;
img.shadowColor = "rgb(0, 0, 0)";
var xSpeed = 0; //px per ms
var ySpeed = 0.15;
function animate(nowTime, lastTime, xPos, yPos) {
// update
if ((img.style.height + yPos) > canvas.height) {
xPos = 0;
yPos = 0;
}
var timeDelta = nowTime - lastTime;
var xDelta = xSpeed * timeDelta;
var yDelta = ySpeed * timeDelta;
// clear
context.clearRect(0, 0, canvas.width, canvas.height);
// shadow
context.shadowOffsetX = 3;
context.shadowOffsetY = 7;
context.shadowBlur = 4;
context.shadowColor = 'rgba(0, 0, 0, 0.4)';
//draw img
context.drawImage(img, xPos, yPos);
if (yPos > canvas.height - img.height ) {
addMarker();
}
else {
requestAnimationFrame(
function(timestamp){
animate(timestamp, nowTime, xPos + xDelta, yPos + yDelta);
}
);
}
}
animate(0, 0, -10, 0);
Here is my current code which animates an image from the top of the canvas element to the bottom and then stops.
Thanks.
context.DrawImage has additional parameters that let you scale your image to your needs:
// var scale is the scaling factor to apply between 0.00 and 1.00
// scale=0.50 will draw the image half-sized
var scale=0.50;
// var y is the top position on the canvas where you want to drawImage your image
var y=0;
context.drawImage(
// draw img
img,
// clip a rectangular portion from img
// starting at [top,left]=[0,0]
// and with width,height == img.width,img.height
0, 0, img.width, img.height,
// draw that clipped portion of of img on the canvas
// at [top,left]=[0,y]
// with width scaled to img.width*scale
// and height scaled to img.height*scale
0, y, img.width*scale, img.height*scale
)
Here's an example you can start with and fit to your own design needs:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var cw = canvas.width;
var ch = canvas.height;
var scale = 1;
var scaleDirection = 1
var iw, ih;
var y = 1;
var yIncrement = ch / 200;
var img = new Image();
img.onload = start;
img.src = "https://dl.dropboxusercontent.com/u/139992952/multple/sun.png";
function start() {
iw = img.width;
ih = img.height;
requestAnimationFrame(animate);
}
function animate(time) {
if (scale > 0) {
requestAnimationFrame(animate);
}
ctx.clearRect(0, 0, cw, ch);
ctx.drawImage(img, 0, 0, iw, ih, 0, y, iw * scale / 100, ih * scale / 100);
scale += scaleDirection;
if (scale > 100) {
scale = 100;
scaleDirection *= -1;
}
y += yIncrement;
}
$("#test").click(function() {
scale = y = scaleDirection = 1;
requestAnimationFrame(animate);
});
body{ background-color: ivory; }
canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<button id="test">Animate Again</button>
<br>
<canvas id="canvas" width=80 height=250></canvas>

Implement HTML canvas image tinting function

First time StackOverflow poster here so please be gentle :)
I am trying to implement image tinting in HTML canvas for a game I'm developing. There were a lot of good suggestions here:
How do i tint an image with HTML5 Canvas?
And I successfully implemented one of those, but the image colours looked too washed out. I was impressed with the results here:
http://www.playmycode.com/blog/2011/06/realtime-image-tinting-on-html5-canvas/
And I tried to play with the code but it's simply not working in the fiddle I'm messing with (can't post a link to JS Fiddle as I don't have enough rep):
function generateRGBKs( img ) {
var w = img.width;
var h = img.height;
var rgbks = [];
var canvas = document.createElement("canvas");
canvas.width = w;
canvas.height = h;
var ctx = canvas.getContext("2d");
ctx.drawImage( img, 0, 0 );
var pixels = ctx.getImageData( 0, 0, w, h ).data;
// 4 is used to ask for 3 images: red, green, blue and
// black in that order.
for ( var rgbI = 0; rgbI < 4; rgbI++ ) {
var canvas = document.createElement("canvas");
canvas.width = w;
canvas.height = h;
var ctx = canvas.getContext('2d');
ctx.drawImage( img, 0, 0 );
var to = ctx.getImageData( 0, 0, w, h );
var toData = to.data;
for (
var i = 0, len = pixels.length;
i < len;
i += 4
) {
toData[i ] = (rgbI === 0) ? pixels[i ] : 0;
toData[i+1] = (rgbI === 1) ? pixels[i+1] : 0;
toData[i+2] = (rgbI === 2) ? pixels[i+2] : 0;
toData[i+3] = pixels[i+3] ;
}
ctx.putImageData( to, 0, 0 );
// image is _slightly_ faster then canvas for this, so convert
var imgComp = new Image();
imgComp.src = canvas.toDataURL();
rgbks.push( imgComp );
}
return rgbks;
}
function generateTintImage( img, rgbks, red, green, blue ) {
var buff = document.createElement( "canvas" );
buff.width = img.width;
buff.height = img.height;
var ctx = buff.getContext("2d");
ctx.globalAlpha = 1;
ctx.globalCompositeOperation = 'copy';
ctx.drawImage( rgbks[3], 0, 0 );
ctx.globalCompositeOperation = 'lighter';
if ( red > 0 ) {
ctx.globalAlpha = red / 255.0;
ctx.drawImage( rgbks[0], 0, 0 );
}
if ( green > 0 ) {
ctx.globalAlpha = green / 255.0;
ctx.drawImage( rgbks[1], 0, 0 );
}
if ( blue > 0 ) {
ctx.globalAlpha = blue / 255.0;
ctx.drawImage( rgbks[2], 0, 0 );
}
return buff;
}
var img = new Image();
img.onload = function() {
var rgbks = generateRGBKs( img );
var tintImg = generateTintImage( img, rgbks, 200, 50, 100 );
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "black";
ctx.fillRect( 0, 0, 100, 100 );
ctx.drawImage( tintImg, 50, 50 );
}
img.src = "https://pbs.twimg.com/profile_images/413816438701309953/uvZMK_gT_normal.jpeg";
I'm sure it's something stupid I've done and nothing wrong with Joe's code - can anyone help me get it working?
Many thanks :)
Because you're accessing the pixel data the image needs to be on the same domain as the code, or you can try using a base64 src.
img.src = "data:image/jpeg;base64,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";
You're breaking CORS policy
Heres a working JSFiddle

Need to create a loop using HTML5 canvas and JavaScript

I am using a jQuery carousel to display 38 different magnifications/positions of a large SVG image. I would ideally like to use some sort of loop to go through all the different sizes, draw to an individual canvas and place one in each of the li's in my carousel. Can anyone help me achieve this. Here's what I tried:
function drawSlides() {
for (var i = 1; i <= 38; i++) {
var currentCanvas = 'myCanvas_' + slideNumber;
// initialise canvas element
var canvas_i = document.getElementById('' + currentCanvas + '');
var context = canvas_i.getContext('2d');
// position of SVG – these measurements are subject to change!
var destX_i = -6940;
var destY_i = -29240;
var destWidth_i = 9373;
var destHeight_i = 30000;
context.drawImage('/path/image.svg',
destX_i, destY_i, destWidth_i, destHeight_i);
// white rectangle background – these are constant
var topLeftCornerX_i = 453;
var topLeftCornerY_i = -10;
var width_i = 370;
var height_i = 480;
context.beginPath();
context.rect(topLeftCornerX_i, topLeftCornerY_i, width_i, height_i);
context.fillStyle = "rgba(255, 255, 255, 1)";
context.fill();
// orange vertical line – these elements are constant
context.moveTo(453, 0);
context.lineTo(453, 460);
context.lineWidth = 2;
context.strokeStyle = "#f5d7cb";
context.stroke();
//orange ball – these are constant
var centerX_ball_i = 453;
var centerY_ball_i = 323;
var radius = 99;
context.beginPath();
context.arc(centerX_ball_i, centerY_ball_i, radius, 0, 2 * Math.PI, false);
var grd_ball_i = context.createLinearGradient(224, 354, 422, 552);
grd_ball_i.addColorStop(0, "#f5d7cb"); // light orange
grd_ball_i.addColorStop(1, "#ff4900"); // dark orange
context.fillStyle = grd_ball_i;
context.fill();
}
};
drawSlides();
This should get you moving:
var numCarouselItems = 38;
var myUL = document.getElementById('carousel');
var items = myUL.childNodes;
var img = new Image;
img.onload = function(){
for (var i=0;i<numCarouselItems;++i){
// Find the nth li, or create it
var li = items[i] || myUL.appendChild(document.createElement('li'));
// Find the nth canvas, or create it
var canvas = li.getElementsByTagName('canvas')[0] ||
li.appendChild(document.createElement('canvas'));
canvas.width = 1; // Erase the canvas, in case it existed
canvas.width = 320; // Set the width and height as desired
canvas.height = 240;
var ctx = canvas.getContext('2d');
// Use your actual calculations for the SVG size/position here
ctx.drawImage( img, 0, 0 );
}
}
// Be sure to set your image source after your load handler is in place
img.src = "foo.svg";

Categories