我正在尝试使用html 5 canvas和javascript在图像上创建一些云型效果。我在主图像上方使用画布绘制图像,但现在我必须随机淡出图像。但是当我尝试使用普通的jquery淡出功能时它似乎不起作用,下面是我的代码。
var canvas = document.getElementById("myCanvas"),
context = canvas.getContext("2d"),
img = new Image();
img.src = '/images/smoke-2.png';
var v = 0;
var vt = 0;
var count = 0;
img.onload = function(){
//console.log(Math.ceil(canvas.width/70));
var t = Math.ceil(canvas.width/5);
var ht = Math.ceil(canvas.height/5);
for (var w = 0; w < t; w++) {
vt = 0;
for (var h = 0; h < ht; h++) {
//console.log(vt);
context.drawImage(img, v, vt);
vt += 5;
count++;
}
v += 5;
//console.log(v);
}
}
任何人都可以帮我解决一下。
答案 0 :(得分:0)
您无法使用for loop
。您应该使用setTimeout
。请根据您的代码尝试以下代码。
var canvas = document.getElementById("myCanvas"),
context = canvas.getContext("2d"),
img = new Image();
img.src = '/images/smoke-2.png';
var v = 0;
var vt = 0;
var count = 0;
img.onload = function(){
var t = Math.ceil(canvas.width/5);
var ht = Math.ceil(canvas.height/5);
var w=0, h=0;
var timer = setTimeout(drawFunc, 1000);
function drawFunc() {
context.drawImage(img, v, vt);
h++;
vt += 5;
count++;
if(h==ht) {
h=0;
vt=0;
w++;
v+=5;
if(w==t) {
clearTimeout(timer);
}
}
timer = setTimeout(drawFunc, 1000);
}
}
答案 1 :(得分:0)
不是真正的答案,但我碰巧做了一些非常相似的事情,涉及从纯色渐变到图像,因此修改了SO和OP的图像(用火和闪电现在是浅色和鲜花)并添加了评论。
使用许多层,渐变,粒子和复合模式绘制图像和淡入fx。底层图像缓慢旋转和缩放。
// create canvas and context
var canvas = document.createElement("canvas");
canvas.style.position = "absolute";
canvas.style.left = canvas.style.top = "0px";
canvas.style.zIndex = 100000;
canvas.style.border = "none";
var ctx = canvas.getContext("2d");
// add to DOM
document.body.appendChild(canvas);
var currentLoopFunction;
var firstRun = true;
var timeoutHandle;
// resize canvas will restart animation
function resize() {
canvas.width = innerWidth;
canvas.height = innerHeight;
ctx.setTransform(1, 0, 0, 1, 0, 0);
// stack overflow is causing problems here so have added
// a timers to delay the restart
if(!firstRun){
clearTimeout(timeoutHandle);
timeoutHandle = setTimeout(()=>currentLoopFunction = restart,500);
//currentLoopFunction = restart;
}
firstRun = false;
}
resize();
currentLoopFunction = loadText;
const fx = {
growRate: 1, // number of pixels per frame on average that the smoke image grows by
smokeMove: 0.01, // rotate the smoke to make it look like its is swirling
ringDist: 0.85, // distance from image center to stop movement of smoke outward. As a fraction of radius ofa canvas bounding circle
centerPull: 0.125, // pull all smoke in towards the center of canvas at start
scaleRange: 5, // the close smoke is to center the larger it is. This sets the max center scale multiplier
pCount: 100, // Approx number of particles to render
flowerScaleGrow: 0.03, // slowly grow flower image to normal scale
flowerScaleStart: 0.9, // scale of flower at start
flowerScaleEnd: 1.3, // scale of flower towards end. Will never get to this value
flowerRotate: 0.01, // rate to rotate flower
flowerRotateStart: -0.6, // Startng angle of flower image
flowerRotateEnd: 0.0, // end angle of flower image
sCurveSlope: 1.2, // slope of s curve at origin (not real slope) must be > 1 and smaller valuesreduce the rate of change
// this controls flower rotate and grow
globalAlphaRate: 0.01, // controls the rate global alpha is reduced
}
function sCurve(x) {
return (2 / (1 + Math.pow(fx.sCurveSlope, -x))) - 1;
}
var imageAspect = 1;
var imageScaleToFill = 1;
var globalAlpha = 1;
var frameCounter; // counts frames
var smoke = new Image;
var flowers = new Image;
var imageCount = 0; // count the image as they load and used to stage setup
// Two radial gradients from transparent white in center to white at edges
// first one is smaller and a softer transition
// The second one is used to cover corners if display canvas aspect ratio is extreme
var ringGrad;
var ringGrad1;
// load the images
smoke.src = "http://www.emqubeweb.com/smoke-2.png";
flowers.src = "http://www.emqubeweb.com/flower.png";
smoke.onload = flowers.onload = function() {
imageCount += 1
};
// draws a particle
function drawImage(p) { // p is particle
ctx.setTransform(p.scale, 0, 0, p.scale, p.x, p.y);
ctx.rotate(p.angle);
ctx.globalAlpha = p.alpha * globalAlpha;
ctx.drawImage(smoke, -smoke.width / 2, -smoke.height / 2);
}
// object that controls particles.
var particles = {
items: [], // array of particles
update() { // updates the scale position, rotation and alpha of particle
var i, p, cw, ch, dx, dy, dist, distMax, area, r;
// get canvas center
cw = canvas.width / 2;
ch = canvas.height / 2;
distMax = Math.sqrt(cw * cw + ch * ch) * fx.ringDist; // extend diagonal max dist from center
// do each particle in turn
for (i = 0; i < this.items.length; i++) {
p = this.items[i];
// get vector from center to particle and normalise it
dx = p.x - cw;
dy = p.y - ch;
dist = Math.sqrt(dx * dx + dy * dy) + 0.001; // the 0.001 added is to stop / by zero
dx /= dist;
dy /= dist;
// move outward. The futher out the slowre it moves
p.x += (1 - dist / distMax) * dx * (p.rand * 0.25 + 0.1);
p.y += (1 - dist / distMax) * dy * (p.rand * 0.25 + 0.1);
// add a little movement along the tangent to the center
p.y -= (1 - dist / distMax) * dx * (p.rand * 0.2 + 0.1);
p.x += (1 - dist / distMax) * dy * (p.rand * 0.2 + 0.1);
// get the particle area
area = (smoke.width * smoke.height) * p.scale;
// increase area and then caculate new scale for the new area
p.scale *= Math.sqrt(area + (Math.random() + Math.random()) * fx.growRate) / Math.sqrt(area);
p.angle += fx.smokeMove * (p.rand * 0.5 + 0.5);
// as particles volume increase reduce the transparency
p.alpha = p.startVol / (area * smoke.height);
}
},
draw() {
var i;;
for (i = 0; i < this.items.length; i++) {
drawImage(this.items[i])
}
}
}
// render loading screen
function loadText() {
ctx.font = "32px arial";
ctx.textAlign = "center";
ctx.fillStyle = "black";
ctx.fillText("Loading images, please wait.", canvas.width / 2, canvas.height / 2);
ctx.fillText("Best viewed fullpage.", canvas.width / 2, canvas.height / 2 + 36);
currentLoopFunction = wait; // set the loop function to wait
}
function blackenSmoke() {
// so the following creates a copy of the smoke image adding some grays to give extra FX
var smoke1 = document.createElement("canvas");
smoke1.width = smoke.width;
smoke1.height = smoke.height;
smoke1.ctx = smoke1.getContext("2d");
// add black
smoke1.ctx.fillStyle = "#d5d";
smoke1.ctx.fillRect(0, 0, smoke.width, smoke.height);
// mask out black with smoke
smoke1.ctx.globalCompositeOperation = "destination-in";
smoke1.ctx.setTransform(0.95, 0, 0, 0.95, smoke.width / 2, smoke.height / 2);
smoke1.ctx.rotate(0.1);
smoke1.ctx.drawImage(smoke, -smoke.width / 2, -smoke.height / 2);
// draw smoke a little smaller and rotated
smoke1.ctx.setTransform(0.93, 0, 0, 0.93, smoke.width / 2, smoke.height / 2);
smoke1.ctx.rotate(-0.1);
smoke1.ctx.globalCompositeOperation = "source-over";
smoke1.ctx.drawImage(smoke, -smoke.width / 2, -smoke.height / 2);
smoke1.ctx.globalCompositeOperation = "multiply";
smoke1.ctx.drawImage(smoke1, -smoke.width / 2, -smoke.height / 2);
// draw once more to bring up the brightness
smoke1.ctx.globalCompositeOperation = "lighten";
smoke1.ctx.drawImage(smoke, -smoke.width / 2, -smoke.height / 2);
smoke1.ctx.globalCompositeOperation = "multiply";
smoke1.ctx.drawImage(smoke1, -smoke.width / 2, -smoke.height / 2);
// set the new smoke image.
smoke = smoke1;
}
// create gradients
function createGradients(){
ringGrad = ctx.createRadialGradient(0, 0, 0, 0, 0, Math.min(canvas.width, canvas.height) / 2);
ringGrad.addColorStop(0, "rgba(255,255,255,0)");
ringGrad.addColorStop(0.2, "rgba(255,255,255,0)");
ringGrad.addColorStop(0.5, "rgba(255,255,255,0.2)");
ringGrad.addColorStop(0.9, "rgba(255,255,255,0.8)");
ringGrad.addColorStop(1, "rgba(255,255,255,1)");
ringGrad1 = ctx.createRadialGradient(0, 0, 0, 0, 0, Math.max(canvas.width, canvas.height) * 0.25);
ringGrad1.addColorStop(0.0, "rgba(255,255,255,0.0)");
ringGrad1.addColorStop(0.6, "rgba(255,255,255,0.0)");
ringGrad1.addColorStop(0.7, "rgba(255,255,255,0.2)");
ringGrad1.addColorStop(0.8, "rgba(255,255,255,0.6)");
ringGrad1.addColorStop(1, "rgba(255,255,255,1)");
}
// Wait for images to load
function wait() {
if (imageCount === 2) {
blackenSmoke();
start();
window.addEventListener("resize", resize);
}
}
function restart() {
particles.items.length = 0;
start();
}
function start() {
var x, y, dx, dy, px, py, dist, scale, cw, ch;
// get the particle width and height to match the canvas
w = canvas.width / Math.ceil(Math.sqrt(fx.pCount));
h = canvas.height / Math.ceil(Math.sqrt(fx.pCount));
// set the particle scale
scale = Math.min(w / smoke.width, h / smoke.height);
// find the center and diagonal distance from center to top left
cw = canvas.width / 2;
ch = canvas.height / 2;
distMax = Math.sqrt(cw * cw + ch * ch); // extend diagonal max dist from center
// add particles
for (y = 0; y < canvas.height; y += h) {
for (x = 0; x < canvas.width; x += w) {
// get particle center location plus randomise by its width and height
px = x + (Math.random() - Math.random()) * w + w / 2;
py = y + (Math.random() - Math.random()) * h + h / 2;
// find he vector and distance from canvas center to particle
dx = px - canvas.width / 2;
dy = py - canvas.height / 2;
dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 5) { // if to close to center particle gets stuck so just only particles at least 5 pixels from center
// move the particle towards the center for start position
px -= dx * fx.centerPull;
py -= dy * fx.centerPull;
// The closer to the center the particle is the bigger it should be.
// dist multiplies the scale
dist = Math.cos((dist / distMax) * Math.PI * 0.5) * fx.scaleRange;
// add the particle. Get the volume approximating a cubic volume for the smoke
particles.items.push({
x: px,
y: py,
rand: Math.random()*0.9 + 0.1, // a constant random per particle for various fx
alpha: 1,
scale: scale * dist,
startVol: smoke.width * smoke.height * smoke.height * scale * dist,
angle: Math.random() * Math.PI * 2,
})
}
}
}
// set the image aspect
imageAspect = flowers.height / flowers.width;
// changed to scale to fit use min (to fill use Math.max)
imageScaleToFill = Math.max(flowers.height / canvas.height, flowers.width / canvas.width);
createGradients();
frameCounter = 0;
currentLoopFunction = fadeIn; // function to loop
}
function fadeIn() {
// clears canvas and renders layers
ctx.globalCompositeOperation = "source-over";
frameCounter += 1;
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.globalAlpha = 1;
// white background layer
ctx.fillStyle = "white";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Main image layer slowly rotated and scaled
var scale = fx.flowerScaleStart + sCurve(frameCounter * fx.flowerScaleGrow) * (fx.flowerScaleEnd - fx.flowerScaleStart);
globalAlpha = 1 - sCurve(frameCounter * fx.globalAlphaRate)
ctx.setTransform(scale * imageScaleToFill, 0, 0, scale * imageScaleToFill, canvas.width / 2, canvas.height / 2);
ctx.rotate(fx.flowerRotateStart + sCurve(frameCounter * fx.flowerRotate) * (fx.flowerRotateEnd - fx.flowerRotateStart));
ctx.drawImage(flowers, -canvas.width / 2, -canvas.width * 0.5 * imageAspect, canvas.width, canvas.width * imageAspect);
// Draw flower image again with multiply to increase the contrast
ctx.globalCompositeOperation = "multiply";
ctx.globalAlpha = 1 - globalAlpha;
ctx.drawImage(flowers, -canvas.width / 2, -(canvas.width / 2) * imageAspect, canvas.width, canvas.width * imageAspect);
ctx.globalAlpha = 1;
// Draw the smoke particles
ctx.globalCompositeOperation = "source-over";
particles.update();
particles.draw();
// draw a white round boarder
ctx.globalCompositeOperation = "lighten";
ctx.setTransform(scale * scale, 0, 0, scale * scale, canvas.width / 2, canvas.height / 2);
ctx.fillStyle = ringGrad;
ctx.fillRect(-canvas.width, -canvas.height, canvas.width * 2, canvas.height * 2);
//Draw smoke image over to ease the transition from white to the smokes grays
ctx.globalCompositeOperation = "source-over";
ctx.globalAlpha = globalAlpha;
ctx.drawImage(smoke, -canvas.width / 2, -canvas.height / 2, canvas.width, canvas.height);
// flat white layer ensures that at start there is only white.
ctx.fillStyle = "white";
ctx.fillRect(-canvas.width, -canvas.height, canvas.width * 2, canvas.height * 2);
// Finnal outer ring gradient to clean up edges if image display aspect is extreme
ctx.globalAlpha = 1;
ctx.fillStyle = ringGrad1;
ctx.fillRect(-canvas.width, -canvas.height, canvas.width * 2, canvas.height * 2);
if (globalAlpha < 0.001) { // when global alpha is very small (well below visible)
currentLoopFunction = restart; // restart
}
}
// main loop calls various functions as needed
function mainLoop() {
currentLoopFunction();
requestAnimationFrame(mainLoop);
}
requestAnimationFrame(mainLoop);
&#13;