明智地展开图像块

时间:2018-04-05 12:45:52

标签: jquery html css

我正在尝试实现图像的展开效果,并且在我的一位在线朋友的帮助下,我已经达到了效果。



//Size of image
var _w = 920;
var _h = 452;
//Fold instance
var _foldA;

//First we load an image to use:
var _img = new Image();
_img.onload = loaded;
_img.src = "http://tecnoweb.bottlementors.com/images/tecno-camon.jpg";


function loaded(e) {
  //Init the fold image
  _foldA = new FoldImage(document.getElementsByClassName("camon-mobile")[0], _w, _h, 4, 3, 3);
  _foldB = new FoldImage(document.getElementsByClassName("camon-sky")[0], _w, _h, 4, 3, 3); //Play around with this, especially last parameter
  _foldA.animIn(); //you can execute this on scroll or with a delay

}

//Class for applying the effect
function FoldImage(_me, _w, _h, _tilesX, _tilesY, _startTileID) {
  var _this = this;
  _me.style.width = _w + "px", _me.style.height = _h + "px";
  //Create canvas tiles
  var _numTiles = _tilesX * _tilesY;
  var _tiles = [];
  var _tileW = Math.round(_w / _tilesX),
    _tileH = Math.round(_h / _tilesY);
  var _animedIn = false;
  for (var i = 0; i < _numTiles; i++) _tiles.push(new FoldTile(i, _me, _tileW, _tileH, _tilesX, _tilesY));

  //Draw on all canvasses
  for (i = 0; i < _numTiles; i++) _tiles[i].drawSection(_img, _tileW, _tileH);

  _this.animIn = function() {
    if (_animedIn) return;
    _animedIn = true;
    for (i = 0; i < _numTiles; i++) _tiles[i].animIn(.4, _startTileID);
  }

  _this.rerun = function() {
    _animedIn = false;
    for (i = 0; i < _numTiles; i++) _tiles[i].reset();
    _this.animIn();
  }

  //This works like a linked list, each cell dispatch an event to trigger the animation for a neighbour
  _me.addEventListener("tileAnim", neighbourCall);
  var _totalCalls = 0;

  function neighbourCall(e) {
    _totalCalls++;
    for (i = 0; i < _numTiles; i++) _tiles[i].neighbourCalledMe(e.detail, _totalCalls);
  }
}


function FoldTile(_id, _container, _tileW, _tileH, _tilesX, _tilesY) {
  var _this = this;
  var _me = document.createElement("div");
  _me.className = "tile";
  var _canvas = document.createElement("canvas");
  _canvas.className = "canvas";
  var _x = (_id % _tilesX) * _tileW,
    _y = Math.floor(_id / _tilesX) * _tileH;
  var _shade = document.createElement("div");
  _shade.className = "shade";
  _me.appendChild(_canvas);
  var _scale = 1; //To-do: adjust for retina screens

  var _oriTileW = _tileW,
    _oriTileH = _tileH;
  var _maxRotX = 90,
    _maxRotY = 90,
    _numTiles = _tilesX * _tilesY;
  var _rotX = 0,
    _rotY = 0;
  var _origin = "0 50%",
    _perspective = 500;
  var _oriX = "0",
    _oriY = "0";
  var _ctx = _canvas.getContext('2d');

  _this.drawSection = function(_img, _tileW, _tileH) {
    _canvas.width = _tileW * _scale, _canvas.height = _tileH * _scale;
    var _x = (_id % _tilesX) * _tileW,
      _y = Math.floor(_id / _tilesX) * _tileH;
    _me.style.left = _x + "px", _me.style.top = _y + "px", _me.style.width = _tileW + "px", _me.style.height = _tileH + "px";
    _ctx.drawImage(_img, (_id % _tilesX) * _oriTileW, Math.floor(_id / _tilesX) * _oriTileH, _oriTileW, _oriTileH, 0, 0, _tileW * _scale, _tileH * _scale);
    _container.appendChild(_me);
  }

  var _animTime = 0;
  var _animInCalled = false;

  _this.animIn = function(_time, _startTileID) {
    _animTime = _time;
    if (_id == _startTileID) {
      _animInCalled = true;
      started();
      return;
    }
    //Find out the first neighbour tiles:
    var _xstart = (_startTileID % _tilesX) * _tileW + _tileW * .5,
      _ystart = Math.floor(_startTileID / _tilesX) * _tileH + _tileH * .5;
    var _mycenterX = _x + _tileW * .5,
      _mycenterY = _y + _tileH * .5;
    var _distanceToStartTile = Math.sqrt(Math.pow((_mycenterX - _xstart), 2) + Math.pow((_mycenterY - _ystart), 2));
    if (_distanceToStartTile < (Math.max(_tileW, _tileH) + 2)) _this.neighbourCalledMe(_startTileID, 0);
  }

  _this.reset = function() {
    _me.style.visibility = "hidden";
    _animInCalled = false;
    _rotX = 0, _rotY = 0;
    _animTime = 0;
    TweenLite.set(_shade, {
      autoAlpha: 1
    });
  }

  //Neighbour finished animIn and is now calling this to start
  _this.neighbourCalledMe = function(_neighbourId, _totalCalls) {
    if (_animInCalled) return;

    //Find distance and relative position: 
    var _xstart = (_neighbourId % _tilesX) * _tileW + _tileW * .5,
      _ystart = Math.floor(_neighbourId / _tilesX) * _tileH + _tileH * .5;
    var _mycenterX = _x + _tileW * .5,
      _mycenterY = _y + _tileH * .5;
    var _distanceToStartTile = Math.sqrt(Math.pow((_mycenterX - _xstart), 2) + Math.pow((_mycenterY - _ystart), 2));

    //Cancel if too far away:
    if (_distanceToStartTile > (Math.max(_tileW, _tileH) + 4)) return;
    _animInCalled = true;

    //Find the axis to rotate around
    if (_mycenterX < _xstart) _rotY = _maxRotY, _oriX = "100%";
    else if (_mycenterX > _xstart) _rotY = -_maxRotY, _oriX = "0";
    else _oriX = "50%";
    if (_mycenterY < _ystart) _rotX = -_maxRotX, _oriY = "100%";
    else if (_mycenterY > _ystart) _rotX = _maxRotX, _oriY = "0";
    else _oriY = "50%";
    //Set origin
    _origin = _oriX + " " + _oriY;
    //Set initial position
    TweenLite.set(_me, {
      rotationX: _rotX,
      rotationY: _rotY,
      transformPerspective: _perspective,
      transformOrigin: _origin
    });

    //Anim in
    var _myTime = _animTime + Math.random() * .3,
      _ease = Quad.easeOut;
    if (_totalCalls > _numTiles * .5) _ease = Back.easeOut, _myTime += .2;
    //Call neighbours when almost there:
    setTimeout(callNeighbour, Math.max(0, _myTime * 1000 * .5));
    _me.appendChild(_shade);
    TweenLite.to(_me, _myTime, {
      rotationX: 0,
      rotationY: 0,
      transformOrigin: _origin,
      transformPerspective: _perspective,
      ease: _ease,
      onStart: started,
      onComplete: animInOver
    });
    TweenLite.to(_shade, _myTime * .9, {
      autoAlpha: 0,
      ease: Quad.easeOut
    });
  }

  function started() {
    _me.style.visibility = "visible";
  }

  function callNeighbour() {
    _container.dispatchEvent(CPCustomEvent("tileAnim", _id));
  }

  function animInOver() {
    if (_id % _tilesX == 0 || _id % _tilesX == (_tilesX - 1) || Math.floor(_id / _tilesY) == 0 || Math.floor(_id / _tilesX) == (_tilesY - 1)) {
      if (_id % _tilesX == 0) _rotY = _maxRotY, _oriX = "100%";
      else if (_id % _tilesX == (_tilesX - 1)) _rotY = -_maxRotY, _oriX = "0";
      else _rotY = 0, _oriX = "50%";
      if (Math.floor(_id / _tilesY) == 0) _rotX = -_maxRotX, _oriY = "100%";
      else if (Math.floor(_id / _tilesX) == (_tilesY - 1)) _rotX = _maxRotX, _oriY = "0";
      else _rotX = 0, _oriY = "50%";
      //Set origin
      _origin = _oriX + " " + _oriY;
      _me.addEventListener("mouseenter", over);
      _me.addEventListener("mouseleave", out);
      _me.addEventListener("mousedown", clicked);
      _me.addEventListener("touchstart", clicked);
    }
  }

  function over(e) {
    TweenLite.to(_me, .3, {
      rotationX: -_rotX * .1 * (Math.random() * .5 + .5),
      rotationY: -_rotY * .1 * (Math.random() * .5 + .5),
      transformOrigin: _origin,
      transformPerspective: _perspective,
      ease: Quad.easeOut
    });
    TweenLite.to(_shade, .3, {
      autoAlpha: .05,
      ease: Quad.easeOut
    });
  }

  function out(e) {
    TweenLite.to(_me, .3, {
      rotationX: 0,
      rotationY: 0,
      transformOrigin: _origin,
      transformPerspective: _perspective,
      ease: Quad.easeOut
    });
    TweenLite.to(_shade, .3, {
      autoAlpha: 0,
      ease: Quad.easeOut
    });
  }

  function clicked(e) {
    e.stopPropagation();
    TweenLite.to(_me, .1, {
      rotationX: -_rotX * .2 * (Math.random() * .5 + .5),
      rotationY: -_rotY * .2 * (Math.random() * .5 + .5),
      transformOrigin: _origin,
      transformPerspective: _perspective,
      ease: Linear.easeNone
    });
    TweenLite.to(_me, .4, {
      rotationX: 0,
      rotationY: 0,
      transformOrigin: _origin,
      delay: .1,
      transformPerspective: _perspective,
      ease: Back.easeOut
    });
    //TweenLite.to(_black, .3, {autoAlpha:.05, ease:Quad.easeOut});
  }
  _this.getTileW = function() {
    return _tileW;
  }
}

//Event util
function CPCustomEvent(_name, _id) {
  var e;
  if (window.CustomEvent) e = new CustomEvent(_name, {
    bubbles: true,
    cancelable: true,
    detail: _id
  });
  else {
    e = document.createEvent('Event');
    e.initEvent(_name, true, true, {
      detail: _id
    });
    e.detail = _id;
  }
  return e;
}
&#13;
body {
  margin: 0;
  background: #f2f2f2;
}

.foldImg {
  position: absolute;
  left: 0;
  top: 0;
}

.tile {
  position: absolute;
  left: 0;
  top: 0;
  visibility: hidden;
}

.tile .canvas {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
}

.tile .shade {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background-color: #f2f2f2;
}
&#13;
<script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/TweenMax.min.js"></script>
<div class="camon-mobile img-responsive" id="camonMobileAnim"></div>
<div class="camon-sky img-responsive" id="camonSkyAnim"></div>
&#13;
&#13;
&#13;

虽然我仍在努力让这个响应并在滚动

上运行

0 个答案:

没有答案