360°旋转图片

今天实现一个触摸屏,可以360°来回滑动的图片效果放在vue项目里面!
网上有很多方法,这里采用其中之一,希望对你有帮助~
按步骤引入:

  1. 在index.html 引入 jq 和一个封装好的js。
    封装好的js如下
(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
    typeof define === 'function' && define.amd ? define(['exports'], factory) :
      (factory((global.SpriteSpin = {})));
}(this, (function (exports) { 'use strict';

  /**
   * @internal
   */
  var Api = /** @class */ (function () {
    function Api(data) {
      this.data = data;
    }
    return Api;
  }());
  /**
   * Adds methods to the SpriteSpin api
   *
   * @public
   */
  function extendApi(methods) {
    var api = Api.prototype;
    for (var key in methods) {
      if (methods.hasOwnProperty(key)) {
        if (api[key]) {
          throw new Error('API method is already defined: ' + key);
        }
        else {
          api[key] = methods[key];
        }
      }
    }
    return api;
  }

  var $$1 = window.jQuery || window.$;

  function getCursorPosition(event) {
    var touches = event.touches;
    var source = event;
    // jQuery Event normalization does not preserve the 'event.touches'
    // try to grab touches from the original event
    if (event.touches === undefined && event.originalEvent !== undefined) {
      touches = event.originalEvent.touches;
    }
    // get current touch or mouse position
    if (touches !== undefined && touches.length > 0) {
      source = touches[0];
    }
    return {
      x: source.clientX || 0,
      y: source.clientY || 0
    };
  }

  var canvas;
  var context;
  function detectionContext() {
    if (context) {
      return context;
    }
    if (!canvas) {
      canvas = document.createElement('canvas');
    }
    if (!canvas || !canvas.getContext) {
      return null;
    }
    context = canvas.getContext('2d');
    return context;
  }
  /**
   * Idea taken from https://github.com/stomita/ios-imagefile-megapixel
   * Detects whether the image has been sub sampled by the browser and does not have its original dimensions.
   * This method unfortunately does not work for images that have transparent background.
   */
  function detectSubsampling(img, width, height) {
    if (!detectionContext()) {
      return false;
    }
    // sub sampling happens on images above 1 megapixel
    if (width * height <= 1024 * 1024) {
      return false;
    }
    // set canvas to 1x1 pixel size and fill it with magenta color
    canvas.width = canvas.height = 1;
    context.fillStyle = '#FF00FF';
    context.fillRect(0, 0, 1, 1);
    // render the image with a negative offset to the left so that it would
    // fill the canvas pixel with the top right pixel of the image.
    context.drawImage(img, -width + 1, 0);
    // check color value to confirm image is covering edge pixel or not.
    // if color still magenta, the image is assumed to be sub sampled.
    try {
      var dat = context.getImageData(0, 0, 1, 1).data;
      return (dat[0] === 255) && (dat[1] === 0) && (dat[2] === 255);
    }
    catch (err) {
      // avoids cross origin exception for chrome when code runs without a server
      return false;
    }
  }

  /**
   *
   */
  function getOuterSize(data) {
    var width = Math.floor(data.width || data.frameWidth || data.target.innerWidth());
    var height = Math.floor(data.height || data.frameHeight || data.target.innerHeight());
    return {
      aspect: width / height,
      height: height,
      width: width
    };
  }
  function getComputedSize(data) {
    var size = getOuterSize(data);
    if (typeof window.getComputedStyle !== 'function') {
      return size;
    }
    var style = window.getComputedStyle(data.target[0]);
    if (!style.width) {
      return size;
    }
    size.width = Math.floor(Number(style.width.replace('px', '')));
    size.height = Math.floor(size.width / size.aspect);
    return size;
  }
  /**
   *
   */
  function getInnerSize(data) {
    var width = Math.floor(data.frameWidth || data.width || data.target.innerWidth());
    var height = Math.floor(data.frameHeight || data.height || data.target.innerHeight());
    return {
      aspect: width / height,
      height: height,
      width: width
    };
  }
  /**
   *
   */
  function getInnerLayout(mode, inner, outer) {
    // get mode
    var isFit = mode === 'fit';
    var isFill = mode === 'fill';
    var isMatch = mode === 'stretch';
    // resulting layout
    var layout = {
      width: '100%',
      height: '100%',
      top: 0,
      left: 0,
      bottom: 0,
      right: 0,
      position: 'absolute',
      overflow: 'hidden'
    };
    // no calculation here
    if (!mode || isMatch) {
      return layout;
    }
    // get size and aspect
    var aspectIsGreater = inner.aspect >= outer.aspect;
    // mode == original
    var width = inner.width;
    var height = inner.height;
    // keep aspect ratio but fit/fill into container
    if (isFit && aspectIsGreater || isFill && !aspectIsGreater) {
      width = outer.width;
      height = outer.width / inner.aspect;
    }
    if (isFill && aspectIsGreater || isFit && !aspectIsGreater) {
      height = outer.height;
      width = outer.height * inner.aspect;
    }
    // floor the numbers
    width = Math.floor(width);
    height = Math.floor(height);
    // position in center
    layout.width = width;
    layout.height = height;
    layout.top = Math.floor((outer.height - height) / 2);
    layout.left = Math.floor((outer.width - width) / 2);
    layout.right = layout.left;
    layout.bottom = layout.top;
    return layout;
  }

  var img;
  /**
   * gets the original width and height of an image element
   */
  function naturalSize(image) {
    // for browsers that support naturalWidth and naturalHeight properties
    if (image.naturalWidth) {
      return {
        height: image.naturalHeight,
        width: image.naturalWidth
      };
    }
    // browsers that do not support naturalWidth and naturalHeight properties have to fall back to the width and
    // height properties. However, the image might have a css style applied so width and height would return the
    // css size. To avoid thet create a new Image object that is free of css rules and grab width and height
    // properties
    //
    // assume that the src has already been downloaded, so no onload callback is needed.
    img = img || new Image();
    img.src = image.src;
    return {
      height: img.height,
      width: img.width
    };
  }

  /**
   * Measures the image frames that are used in the given data object
   */
  function measure(images, options) {
    if (images.length === 1) {
      return [measureSheet(images[0], options)];
    }
    else if (options.framesX && options.framesY) {
      return measureMutipleSheets(images, options);
    }
    else {
      return measureFrames(images, options);
    }
  }
  function measureSheet(image, options) {
    var result = { id: 0, sprites: [] };
    measureImage(image, options, result);
    var frames = options.frames;
    var framesX = Number(options.framesX) || frames;
    var framesY = Math.ceil(frames / framesX);
    var frameWidth = Math.floor(result.width / framesX);
    var frameHeight = Math.floor(result.height / framesY);
    var divisor = result.isSubsampled ? 2 : 1;
    for (var i = 0; i < frames; i++) {
      var x = (i % framesX) * frameWidth;
      var y = Math.floor(i / framesX) * frameHeight;
      result.sprites.push({
        id: i,
        x: x, y: y,
        width: frameWidth,
        height: frameHeight,
        sampledX: x / divisor,
        sampledY: y / divisor,
        sampledWidth: frameWidth / divisor,
        sampledHeight: frameHeight / divisor
      });
    }
    return result;
  }
  function measureFrames(images, options) {
    var result = [];
    for (var id = 0; id < images.length; id++) {
      // TODO: optimize
      // dont measure images with same size twice
      var sheet = measureSheet(images[id], { frames: 1, framesX: 1, detectSubsampling: options.detectSubsampling });
      sheet.id = id;
      result.push(sheet);
    }
    return result;
  }
  function measureMutipleSheets(images, options) {
    var result = [];
    for (var id = 0; id < images.length; id++) {
      // TODO: optimize
      // dont measure images with same size twice
      var sheet = measureSheet(images[id], {
        frames: undefined,
        framesX: options.framesX,
        framesY: options.framesY,
        detectSubsampling: options.detectSubsampling
      });
      sheet.id = id;
      result.push(sheet);
    }
    return result;
  }
  function measureImage(image, options, result) {
    var size = naturalSize(image);
    result.isSubsampled = options.detectSubsampling && detectSubsampling(image, size.width, size.height);
    result.width = size.width;
    result.height = size.height;
    result.sampledWidth = size.width / (result.isSubsampled ? 2 : 1);
    result.sampledHeight = size.height / (result.isSubsampled ? 2 : 1);
    return result;
  }
  function findSpecs(metrics, frames, frame, lane) {
    var spriteId = lane * frames + frame;
    var sheetId = 0;
    var sprite = null;
    var sheet = null;
    while (true) {
      sheet = metrics[sheetId];
      if (!sheet) {
        break;
      }
      if (spriteId >= sheet.sprites.length) {
        spriteId -= sheet.sprites.length;
        sheetId++;
        continue;
      }
      sprite = sheet.sprites[spriteId];
      break;
    }
    return { sprite: sprite, sheet: sheet };
  }

  function indexOf(element, arr) {
    for (var i = 0; i < arr.length; i++) {
      if (arr[i] === element) {
        return i;
      }
    }
  }
  function noop() {
    //
  }
  function preload(opts) {
    var src;
    var input = opts.source;
    src = typeof input === 'string' ? [input] : input;
    // const src: string[] =  ? [opts.source] : opts.source
    var images = [];
    var targetCount = (opts.preloadCount || src.length);
    var onInitiated = opts.initiated || noop;
    var onProgress = opts.progress || noop;
    var onComplete = opts.complete || noop;
    var count = 0;
    var completed = false;
    var firstLoaded = false;
    var tick = function () {
      count += 1;
      onProgress({
        index: indexOf(this, images),
        loaded: count,
        total: src.length,
        percent: Math.round((count / src.length) * 100)
      });
      firstLoaded = firstLoaded || (this === images[0]);
      if (firstLoaded && !completed && (count >= targetCount)) {
        completed = true;
        onComplete(images);
      }
    };
    for (var _i = 0, src_1 = src; _i < src_1.length; _i++) {
      var url = src_1[_i];
      var img = new Image();
      // push result
      images.push(img);
      // bind logic, dont care about abort/errors
      img.onload = img.onabort = img.onerror = tick;
      // begin load
      img.src = url;
    }
    onInitiated(images);
  }

  function padNumber(num, length, pad) {
    var result = String(num);
    while (result.length < length) {
      result = String(pad) + result;
    }
    return result;
  }
  /**
   * Generates an array of source strings
   *
   * @remarks
   * Takes a template string and generates an array of strings by interpolating {lane} and {frame} placeholders.
   *
   * ```
   * sourceArray('http://example.com/image_{frame}.jpg, { frame: [1, 3], digits: 2 })
   * // gives:
   * // [ 'http://example.com/image_01.jpg', 'http://example.com/image_02.jpg', 'http://example.com/image_03.jpg' ]
   *
   * sourceArray('http://example.com/image_FRAME.jpg, { frame: [1, 3], digits: 2, framePlacer: 'FRAME' })
   * // gives:
   * // [ 'http://example.com/image_01.jpg', 'http://example.com/image_02.jpg', 'http://example.com/image_03.jpg' ]
   * ```
   *
   * @param template - The template string
   * @param opts - Interpolation options
   *
   * @public
   */
  function sourceArray(template, opts) {
    var digits = opts.digits || 2;
    var lPlacer = opts.lanePlacer || '{lane}';
    var fPlacer = opts.framePlacer || '{frame}';
    var fStart = 0;
    var fEnd = 0;
    if (opts.frame) {
      fStart = opts.frame[0];
      fEnd = opts.frame[1];
    }
    var lStart = 0;
    var lEnd = 0;
    if (opts.lane) {
      lStart = opts.lane[0];
      lEnd = opts.lane[1];
    }
    var result = [];
    for (var lane = lStart; lane <= lEnd; lane += 1) {
      for (var frame = fStart; frame <= fEnd; frame += 1) {
        result.push(template
          .replace(lPlacer, padNumber(lane, digits, '0'))
          .replace(fPlacer, padNumber(frame, digits, '0')));
      }
    }
    return result;
  }

  /**
   * The namespace that is used to bind functions to DOM events and store the data object
   */
  var namespace = 'spritespin';
  /**
   * Event names that are recognized by SpriteSpin. A module can implement any of these and they will be bound
   * to the target element on which the plugin is called.
   */
  var eventNames = [
    'mousedown',
    'mousemove',
    'mouseup',
    'mouseenter',
    'mouseover',
    'mouseleave',
    'mousewheel',
    'wheel',
    'click',
    'dblclick',
    'touchstart',
    'touchmove',
    'touchend',
    'touchcancel',
    'selectstart',
    'gesturestart',
    'gesturechange',
    'gestureend'
  ];
  /**
   *
   */
  var callbackNames = [
    'onInit',
    'onProgress',
    'onLoad',
    'onFrameChanged',
    'onFrame',
    'onDraw',
    'onComplete',
    'onDestroy'
  ];
  /**
   * Names of events for that the default behavior should be prevented.
   */
  var eventsToPrevent = [
    'dragstart'
  ];
  /**
   * Default set of SpriteSpin options. This also represents the majority of data attributes that are used during the
   * lifetime of a SpriteSpin instance. The data is stored inside the target DOM element on which the plugin is called.
   */
  var defaults = {
    source: undefined,
    width: undefined,
    height: undefined,
    frames: undefined,
    framesX: undefined,
    lanes: 1,
    sizeMode: undefined,
    renderer: 'canvas',
    lane: 0,
    frame: 0,
    frameTime: 40,
    animate: true,
    retainAnimate: false,
    reverse: false,
    loop: true,
    stopFrame: 0,
    wrap: true,
    wrapLane: false,
    sense: 1,
    senseLane: undefined,
    orientation: 'horizontal',
    detectSubsampling: true,
    preloadCount: undefined,
    touchScrollTimer: [200, 1500],
    responsive: undefined,
    plugins: undefined
  };

  function noop$1() {
    // noop
  }
  function wrapConsole(type) {
    return console && console[type] ? function () {
      var args = [];
      for (var _i = 0; _i < arguments.length; _i++) {
        args[_i] = arguments[_i];
      }
      return console.log.apply(console, args);
    } : noop$1;
  }
  var log = wrapConsole('log');
  var warn = wrapConsole('warn');
  var error = wrapConsole('error');
  function toArray(value) {
    return Array.isArray(value) ? value : [value];
  }
  /**
   * clamps the given value by the given min and max values
   */
  function clamp(value, min, max) {
    return (value > max ? max : (value < min ? min : value));
  }
  /**
   *
   */
  function wrap(value, min, max, size) {
    while (value > max) {
      value -= size;
    }
    while (value < min) {
 
要实现一个旋转的 CSS 3D 世界,我们需要使用以下属性: - `transform-style: preserve-3d;`:将子元素保留在 3D 空间中 - `transform-origin: center center;`:设置元素的变换原点为中心点 - `transform: rotateY(0deg);`:沿 Y 轴旋转元素 为了创建一个 3D 魔方,我们可以使用六个面的 div 元素,并将它们组合在一起。每个面都需要设置不同的背景颜色或图片。然后将它们放置在一个容器 div 中,并设置容器 div 的宽度和高度。这将是我们的 3D 空间。 接下来,我们需要通过 CSS 3D 变换将容器 div 旋转。我们可以使用 `@keyframes` 规则来定义动画,并将其应用于容器 div。 以下是 HTML 和 CSS 代码示例,可以实现一个 360° 旋转的水晶魔方: HTML 代码: ```html <div class="cube"> <div class="cube-face front"></div> <div class="cube-face back"></div> <div class="cube-face left"></div> <div class="cube-face right"></div> <div class="cube-face top"></div> <div class="cube-face bottom"></div> </div> ``` CSS 代码: ```css .cube { width: 200px; height: 200px; transform-style: preserve-3d; animation: spin 10s linear infinite; } .cube-face { position: absolute; width: 200px; height: 200px; border: 1px solid black; box-sizing: border-box; } .front { transform: translateZ(100px); background-color: red; } .back { transform: translateZ(-100px) rotateY(180deg); background-color: orange; } .left { transform: translateX(-100px) rotateY(-90deg); background-color: yellow; } .right { transform: translateX(100px) rotateY(90deg); background-color: green; } .top { transform: translateY(-100px) rotateX(90deg); background-color: blue; } .bottom { transform: translateY(100px) rotateX(-90deg); background-color: purple; } @keyframes spin { from { transform: rotateY(0deg); } to { transform: rotateY(360deg); } } ``` 在这个示例中,我们使用 `translateZ()`、`translateX()` 和 `translateY()` 函数来移动每个面到正确的位置,使用 `rotateX()`、`rotateY()` 和 `rotateZ()` 函数来旋转每个面。我们还将容器 div 设置为无限旋转的动画,并应用了 10 秒的线性时间函数。 这个示例可以通过浏览器查看效果。当你运行代码时,你会看到一个 360° 旋转的水晶魔方。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值