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