之前通过treesixty.js 插件实现了可拖拽的360度环拍物品展示 H5实现可拖动的360度环拍物品展示(1)
现在使用另外一个方法来实现类似的效果。
需要用到的图片为:
一张初始视角jpg图片和一张高相同的长条图,长条图包含每张角度物品图片。
实现过程
html
360 Degrees
css
html * {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
*, *::after, *::before {
box-sizing: border-box;
}
html {
font-size: 62.5%;
}
body {
font-size: 1.6rem;
font-family: "Lato", sans-serif;
color: #ffffff;
background-color: #f6f6f6;
/* overflow: hidden; */
}
a {
color: #b54240;
text-decoration: none;
}
img {
max-width: 100%;
}
.cd-product-viewer-wrapper {
text-align: center;
}
.cd-product-viewer-wrapper > div {
display: inline-block;
}
.cd-product-viewer-wrapper .product-viewer {
position: relative;
z-index: 1;
display: inline-block;
overflow: hidden;
}
.cd-product-viewer-wrapper img {
display: block;
position: relative;
z-index: 1;
}
.cd-product-viewer-wrapper .product-sprite {
position: absolute;
z-index: 2;
top: 0;
left: 0;
height: 100%;
width: 3400%; /*注意:这里的宽度也是小图片的数量*100%*/
background: url(../img/whitecar.png) no-repeat center center;
background-size: 100%;
opacity: 0;
-webkit-transition: opacity 0.3s;
-moz-transition: opacity 0.3s;
transition: opacity 0.3s;
}
.cd-product-viewer-wrapper.loaded .product-sprite {
opacity: 1;
cursor: ew-resize;
}
main.js
jQuery(document).ready(function($){
var productViewer = function(element) {
this.element = element;
this.handleContainer = this.element.find('.cd-product-viewer-handle');
this.handleFill = this.handleContainer.children('.fill');
this.handle = this.handleContainer.children('.handle');
this.imageWrapper = this.element.find('.product-viewer');
this.slideShow = this.imageWrapper.children('.product-sprite');
this.frames = this.element.data('frame');
//increase this value to increase the friction while dragging on the image - it has to be bigger than zero
this.friction = this.element.data('friction');
this.visibleFrame = 0;
this.loaded = false;
this.animating = false;
this.xPosition = 0;
this.loadFrames();
}
productViewer.prototype.loadFrames = function() {
var self = this,
imageUrl = this.slideShow.data('image'),
newImg = $('');
this.loading('0.5');
//you need this to check if the image sprite has been loaded
newImg.attr('src', imageUrl).load(function() {
$(this).remove();
self.loaded = true;
}).each(function(){
image = this;
if(image.complete) {
$(image).trigger('load');
}
});
}
productViewer.prototype.loading = function(percentage) {
var self = this;
transformElement(this.handleFill, 'scaleX('+ percentage +')');
setTimeout(function(){
if( self.loaded ){
//sprite image has been loaded
self.element.addClass('loaded');
transformElement(self.handleFill, 'scaleX(1)');
self.dragImage();
if(self.handle) self.dragHandle();
} else {
//sprite image has not been loaded - increase self.handleFill scale value
var newPercentage = parseFloat(percentage) + .1;
if ( newPercentage < 1 ) {
self.loading(newPercentage);
} else {
self.loading(parseFloat(percentage));
}
}
}, 500);
}
//draggable funtionality - credits to http://css-tricks.com/snippets/jquery/draggable-without-jquery-ui/
productViewer.prototype.dragHandle = function() {
//implement handle draggability
var self = this;
self.handle.on('mousedown vmousedown', function (e) {
//console.log("dragHandle")
self.handle.addClass('cd-draggable');
var dragWidth = self.handle.outerWidth(),
containerOffset = self.handleContainer.offset().left,
containerWidth = self.handleContainer.outerWidth(),
minLeft = containerOffset - dragWidth/2,
maxLeft = containerOffset + containerWidth - dragWidth/2;
self.xPosition = self.handle.offset().left + dragWidth - e.pageX;
self.element.on('mousemove vmousemove', function (e) {
if( !self.animating) {
self.animating = true;
( !window.requestAnimationFrame )
? setTimeout(function(){self.animateDraggedHandle(e, dragWidth, containerOffset, containerWidth, minLeft, maxLeft);}, 100)
: requestAnimationFrame(function(){self.animateDraggedHandle(e, dragWidth, containerOffset, containerWidth, minLeft, maxLeft);});
}
}).one('mouseup vmouseup', function (e) {
self.handle.removeClass('cd-draggable');
self.element.off('mousemove vmousemove');
});
e.preventDefault();
}).on('mouseup vmouseup', function (e) {
self.handle.removeClass('cd-draggable');
});
}
productViewer.prototype.animateDraggedHandle = function(e, dragWidth, containerOffset, containerWidth, minLeft, maxLeft) {
// console.log("animateDraggedHandle")
var self = this;
var leftValue = e.pageX + self.xPosition - dragWidth;
// constrain the draggable element to move inside his container
if (leftValue < minLeft) {
leftValue = minLeft;
} else if (leftValue > maxLeft) {
leftValue = maxLeft;
}
var widthValue = Math.ceil( (leftValue + dragWidth / 2 - containerOffset) * 1000 / containerWidth)/10;
self.visibleFrame = Math.ceil( (widthValue * (self.frames-1))/100 );
//update image frame
self.updateFrame();
//update handle position
$('.cd-draggable', self.handleContainer).css('left', widthValue + '%').one('mouseup vmouseup', function () {
$(this).removeClass('cd-draggable');
});
self.animating = false;
}
productViewer.prototype.dragImage = function() {
//implement image draggability
var self = this;
self.slideShow.on('mousedown vmousedown', function (e) {
self.slideShow.addClass('cd-draggable');
var containerOffset = self.imageWrapper.offset().left,
containerWidth = self.imageWrapper.outerWidth(),
minFrame = 0,
maxFrame = self.frames - 1;
self.xPosition = e.pageX;
self.element.on('mousemove vmousemove', function (e) {
if( !self.animating) {
self.animating = true;
( !window.requestAnimationFrame )
? setTimeout(function(){self.animateDraggedImage(e, containerOffset, containerWidth);}, 100)
: requestAnimationFrame(function(){self.animateDraggedImage(e, containerOffset, containerWidth);});
}
}).one('mouseup vmouseup', function (e) {
self.slideShow.removeClass('cd-draggable');
self.element.off('mousemove vmousemove');
self.updateHandle();
});
e.preventDefault();
}).on('mouseup vmouseup', function (e) {
self.slideShow.removeClass('cd-draggable');
});
}
productViewer.prototype.animateDraggedImage = function(e, containerOffset, containerWidth) {
var self = this;
var leftValue = self.xPosition - e.pageX;
var widthValue = Math.ceil( (leftValue) * 100 / ( containerWidth * self.friction ));
var frame = (widthValue * (self.frames-1))/100;
if( frame > 0 ) {
frame = Math.floor(frame);
} else {
frame = Math.ceil(frame);
}
var newFrame = self.visibleFrame + frame;
if (newFrame < 0) {
newFrame = self.frames - 1;
} else if (newFrame > self.frames - 1) {
newFrame = 0;
}
if (newFrame == 0 || newFrame == 15){
console.log(newFrame,"yes")
}
if( newFrame != self.visibleFrame ) {
self.visibleFrame = newFrame;
self.updateFrame();
self.xPosition = e.pageX;
}
self.animating = false;
}
productViewer.prototype.updateHandle = function() {
if(this.handle) {
var widthValue = 100*this.visibleFrame/this.frames;
this.handle.animate({'left': widthValue + '%'}, 0);//进度条更新延迟
}
}
productViewer.prototype.updateFrame = function() {
var transformValue = - (100 * this.visibleFrame/this.frames);
console.log("1111",transformValue)
// if(-93.75