【问题标题】:looping through and displaying one sprite or multiple repeating images in multiple positions循环播放并在多个位置显示一个精灵或多个重复图像
【发布时间】:2017-12-05 09:56:18
【问题描述】:

我正在处理我的新项目,我想在其中显示大约 20-30 个小 png 图像中的一种马赛克。所有图像都会重复多次。最后,我想得到很多分散在 csv 形状容器周围的图像,这些图像会稍微移动/摇晃,可能是在鼠标移动时。

现在我尝试在 javascript 中遍历图像精灵并在每个循环中更改精灵位置,但是...

由于覆盖变量,我无法同时显示同一精灵的多个位置。 即使我会以某种方式解决与 html5 画布规范相关的动画会出现一些问题,我也可能不得不将每个图像的一些属性保存为画布,然后就可以绘制并忘记。 有人可以给我一些关于如何解决我的问题的提示吗?也许有人有类似的项目?我愿意接受任何建议和解决方案。

这是我开始使用的一些代码,它是在我尝试通过循环更改变量名之前,因为它没有让我更接近解决方案。我从谷歌图形中添加了一些随机精灵,只是为了举例(暂时没有原创)。

window.onload = function() {
  var canvas = document.getElementById('canvas');
  var context = canvas.getContext('2d');
  for (i = 0; i < 10; i++) {
  for (i = 0; i < 5; i++) {
    var sprite = new Image();
    var swidth = 260;
    var sheight = 260;

    var randomWidth = Math.random() * document.getElementById('canvas');
    var randomHeight = Math.random() * document.getElementById('canvas');

    var cx = randomWidth;
    var cy = randomHeight;
    var sx = i * 260;
    var sy = 0;
    sprite.onload = function() {
      context.drawImage(sprite, sx, sy, swidth, sheight, cx, cy, 260, 213);
    };
    sprite.src = 'https://cdn.codeandweb.com/blog/2016/05/10/how-to-create-a-sprite-sheet/spritestrip.png';
  }
 }
}

提前致谢

【问题讨论】:

  • 为每个精灵分配一个唯一的 ID,或者在 JS 处理程序中使用this,因此您指的是触发事件的精灵。无论如何,请编辑您的问题以显示您迄今为止尝试过的代码。
  • 如何使用 CSS 动画和动画延迟?然后,您可以从 javascript 驱动一些 CSS 值从一个类切换到另一个 .如果你知道比例图片和精灵数量,你也可以同时使用背景大小和高度/宽度这是一个简单的CSS示例来说明这个想法codepen.io/gc-nomade/pen/gReWRR

标签: javascript jquery css html canvas


【解决方案1】:

只需使用数组或基于数组的列表对象。 Javascript 的对象非常灵活,您可以根据需要混合和匹配属性和行为。

在示例中,我创建了一个 list 对象,该对象包含一个项目列表、一个添加项目的函数 (list.add)、删除所有项目 (list.empty),以及一个用于处理所有项目的迭代器 (@ 987654324@)

然后是一个spriteSheet 对象,它加载图像并创建一个精灵表(在我拍摄您的图像并计算出动画与图像大小相关时作弊)。 sprite Sheet 对象还创建sprite 对象。

然后我有一些用于渲染和动画精灵的对象,以及一个处理摆动 FX 的原型对象(用于速度)

然后从名为 walkSprites 的 spriteSheet 对象创建步行动画的精灵表(图片来自 Google 图形,如 OP 的问题中所述),该对象用于创建基本精灵。

然后开始一个动画循环,调整画布大小以适应页面并创建 100 个精灵。我首先创建了一个只有 x,y 位置、缩放和旋转的基本精灵,然后我添加了 Wobble 对象的行为。

全部在sn-p中。单击并按住按钮以启动动画。

const ctx = canvas.getContext("2d");

const U = undefined; 
const doFor = (count, callback) => {var i = 0; while (i < count && callback(i ++) !== true ); };
const randI = (min, max = min + (min = 0)) => (Math.random() * (max - min) + min) | 0;
const rand  = (min, max = min + (min = 0)) => Math.random() * (max - min) + min;

const mouse  = {x : 0, y : 0, button : false}
function mouseEvents(e){
	mouse.x = e.pageX;
	mouse.y = e.pageY;
	mouse.button = e.type === "mousedown" ? true : e.type === "mouseup" ? false : mouse.button;
}
["down","up","move"].forEach(name => document.addEventListener("mouse"+name,mouseEvents));


const list = {
  items : null,
  add(item){ this.items.push(item); return item },
  empty(){ this.items.length = 0 },
  eachItem(callback){
    var i;
    for(i = 0; i < this.items.length; i++){
      callback(this.items[i],i);
    }
  },
}
const spriteSheet = {
  image : null,
  ready : false,
  load(URL){
    this.image = new Image;
    this.image.src = URL;
    this.image.onload = ()=>{
      const sprites = [];
      const w = this.image.width;
      const h = this.image.height;
      for(var i = 0; i < w/h; i++){
        sprites.push({x : i * h, y : 0, w : h,h : h});
      }
      this.image.sprites = sprites;
      this.ready = true;
    }
  },
  create(index,x,y,scale,rot){
     return Object.assign({},sprite,{image:this.image,index,x,y,scale,rot} );
  },
}
const sprite = {
  draw(){
    ctx.setTransform(this.scale,0,0,this.scale,this.x,this.y);
    ctx.rotate(this.rot);
    const spr = this.image.sprites[this.index];
    const w = spr.w;
    const h = spr.h;
    ctx.drawImage(this.image,spr.x,spr.y,w,h,-w/2,-h/2,w,h);
  }
}
function FChase(val,accel,drag){
    this.val = val;
    this.valChase = 0;
    this.valReal = 0;
    this.accel = accel;
    this.drag = drag;
    
}
FChase.prototype = {
    update(val = this.valReal){
        this.valChase += (this.val-this.valReal) * this.accel;
        this.valChase *= this.drag;
        this.valReal += this.valChase;
        return this.valReal;
    },
    kick(amount){
        this.valChase += amount;
    },
    
}
const accel = 0.15;
const drag = 0.7;
const animSpeed = 100;
const wobble = {
    init(){
        this.xc = new FChase(this.x,accel,drag);
        this.yc = new FChase(this.y,accel,drag);
        this.rc = new FChase(this.rot,accel,drag);
        this.sc = new FChase(this.scale,accel,drag);
        this.animSpeed = rand(0.2,1.2);
        this.animOffset = rand(1);
        return this;
    },
    update(){
        this.index = (((globalTime / animSpeed) * this.animSpeed + this.animOffset * this.image.sprites.length) | 0) % this.image.sprites.length;
        this.x = this.xc.update(this.x);
        this.y = this.yc.update(this.x);
        this.scale = this.sc.update(this.scale);
        this.rot = this.rc.update(this.rot);
    },
    kick(){
        this.xc.kick(rand(-40,40));
        this.yc.kick(rand(-40,40));
       // this.sc.kick(rand(-0.1,0.1));
        this.rc.kick(rand(-1,1));
    }
}
// create a sprite sheet and load media
const walkSprites = Object.assign({},spriteSheet);
walkSprites.load("https://cdn.codeandweb.com/blog/2016/05/10/how-to-create-a-sprite-sheet/spritestrip.png");

// create a list for the sprites.
const spriteList = Object.assign({},list,{items:[]});  

// create 100 sprites
const spriteCount = 100;
function createSprites(){
  spriteList.empty();
  doFor(spriteCount,i=>{
    var spr = spriteList.add(
      walkSprites.create(
        randI(6),  // image may not have loaded, but I know how many sprites there are
        randI(canvas.width ), // pos
        randI(canvas.height),
        rand(0.25,0.5), // scale
        rand(Math.PI*2), // rotation
      )
    );
    spr = Object.assign(spr,wobble).init();
  })
}
// use requestAnimationFrame to animate
var w = canvas.width;
var h = canvas.height;
var cw = w / 2;  // center 
var ch = h / 2;
var globalTime;
var frameCount = 0;
// main update function
function update(timer){
    globalTime = timer;
    frameCount += 1;
    ctx.setTransform(1,0,0,1,0,0); // reset transform
    ctx.globalAlpha = 1;           // reset alpha
    if(w !== innerWidth || h !== innerHeight){
      cw = (w = canvas.width = innerWidth) / 2;
      ch = (h = canvas.height = innerHeight) / 2;
      createSprites();
    }else{
      ctx.clearRect(0,0,w,h);
    }
    if(walkSprites.ready){
        if(mouse.button){
            spriteList.eachItem((sprite,i)=>{
              if(frameCount % 20 === i % 20){
                sprite.kick()
              }
            });
        }
        spriteList.eachItem(sprite=>sprite.update());
        spriteList.eachItem(sprite=>sprite.draw());
    }
    requestAnimationFrame(update);
}
requestAnimationFrame(update);
canvas, span{ position : absolute; top : 0px; left 0px; }
span {
  z-index:10;
  font-family:arial black;
  font-size:34px;
  color : yellow;
 }
<span >CLICK HOLD to KICK animations</span>
<canvas id="canvas"></canvas>

【讨论】:

  • 谢谢,你让我很开心!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-04
  • 2012-08-27
  • 1970-01-01
相关资源
最近更新 更多