@ -0,0 +1,51 @@
|
||||
--- |
||||
layout: post |
||||
title: "Apple iPhone 6 Plus review" |
||||
created: Jan 21, 2015 |
||||
categories: |
||||
- review |
||||
tags: Apple |
||||
--- |
||||
<link rel="stylesheet" href="/sites/2015/01/iphone6plus/2020/twentytwenty.css" type="text/css" media="screen" /> |
||||
|
||||
As everyone knew, it was big and lasted long. No argument that it was one of the best iPhone so far and it was one of the best phones you could buy in 2014. |
||||
|
||||
I didn't think iPhone 6 Plus required any review to see whether iPhone was good enough or not. However, you might like to see how it stacked up with others. |
||||
|
||||
<div id="container1"><img src="/sites/2015/01/iphone6plus/many-off.jpg" /><img src="/sites/2015/01/iphone6plus/many-on.jpg" /></div> |
||||
|
||||
It was huge. But I had yet to find one that wanted smaller phones after they had used a big one. I would pick big bulky one over small in both physical dimension and battery life any day; luckily with all goodnesses iPhone 6 Plus had, it was not bulky in any way. |
||||
|
||||
[![many-side](/sites/2015/01/iphone6plus/many-side-sm.jpg)](/sites/2015/01/iphone6plus/many-side.jpg) [![stack](/sites/2015/01/iphone6plus/stack-sm.jpg)](/sites/2015/01/iphone6plus/stack.jpg) |
||||
|
||||
[![case](/sites/2015/01/iphone6plus/case-sm.jpg)](/sites/2015/01/iphone6plus/case.jpg) [![bottom](/sites/2015/01/iphone6plus/bottom-sm.jpg)](/sites/2015/01/iphone6plus/bottom.jpg) |
||||
|
||||
[![back](/sites/2015/01/iphone6plus/back-sm.jpg)](/sites/2015/01/iphone6plus/back.jpg) [![lens](/sites/2015/01/iphone6plus/lens-sm.jpg)](/sites/2015/01/iphone6plus/lens.jpg) |
||||
|
||||
## Impression |
||||
|
||||
![iphone-g3](/sites/2015/01/iphone6plus/iphone-g3-bottom.jpg) |
||||
|
||||
The best thing of every iPhone was iOS undeniably. I wasn't iOS die hard fan, but I couldn't say that any other OS was more polished either. With a solid integration of Apple devices including AppleTV, AirPlay, and AirPrint. It was very difficult to beat. Apple was the only company having the most complete circle. You might argue that Android also had Chromecast, miracast and such. Chromecast was great if you were using stock Android, but it was almost useless when you had many top Android phones like Galaxy Note 4 or LG G3. The Integration wasn't there for every Android's. |
||||
|
||||
> IMHO, iPhone 6 Plus wasn't a cutting edge technology or anything, but it was a solid all around performer. |
||||
|
||||
Apps on iOS were another huge plus; there were only a few app categories which Android prevailed. Mostly they weren't for regular users either. |
||||
|
||||
![touch-id](/sites/2015/01/iphone6plus/touch-id.jpg) |
||||
|
||||
Touch ID was something that once you used it, you couldn't live without. It was way too convenient to unlock the phone and fill out password in App Store yet still remained safe. |
||||
|
||||
For iPhone 6 Plus, it didn't matter if you were a heavy user or not, you would not need to carry any power bank along. This phone lasted over a day undoubtedly. It might even last couple days on a single charge if lightly used. If I remember correctly, only once I had lower than 30% battery before going to bed after over a month experience. |
||||
|
||||
![volume](/sites/2015/01/iphone6plus/volume.jpg) |
||||
|
||||
I didn't know if anyone felt the way I did. I always thought of iPhone as a fragile phone. It needed care or a protection. It needed a case while I rarely had any sort of case on other phones. I didn't know if I could count this as cons or not. Anyway, a real con was its price tag. iPhone was never cheap, but with the money buying this phone you could buy a whole MacBook Air. It sounded expensive as hell. |
||||
|
||||
On software side, I was a bit skeptical about how apps would look in on a bigger screen since iOS didn't really have that fluid layout like Android apps did and the way iPhone apps displaying iPad wasn't ideal. What I found was even apps which hadn't updated to the latest SDK didn't look that bad at all. I couldn't distinguish one from the other if stretchy keyboard didn't showed up. Although I hadn't seen any app (but Apple's ones) taking advantage of iPad-like landscape layout, it was safe to assume that major apps would update correspondingly. This was norm for iOS apps anyway. |
||||
|
||||
## Verdict |
||||
|
||||
Buy one if it didn't break your bank. You would find hard to have any comparable pleasure with other phones. |
||||
|
||||
<script src="/sites/2015/01/iphone6plus/2020/jquery-2.1.3.min.js"></script><script src="/sites/2015/01/iphone6plus/2020/jquery.event.move.js"></script><script src="/sites/2015/01/iphone6plus/2020/jquery.twentytwenty.js"></script><script> $(window).load(function(){ $("#container1").twentytwenty();}); </script> |
@ -0,0 +1,586 @@
|
||||
// jquery.event.move
|
||||
//
|
||||
// 1.3.6
|
||||
//
|
||||
// Stephen Band
|
||||
//
|
||||
// Triggers 'movestart', 'move' and 'moveend' events after
|
||||
// mousemoves following a mousedown cross a distance threshold,
|
||||
// similar to the native 'dragstart', 'drag' and 'dragend' events.
|
||||
// Move events are throttled to animation frames. Move event objects
|
||||
// have the properties:
|
||||
//
|
||||
// pageX:
|
||||
// pageY: Page coordinates of pointer.
|
||||
// startX:
|
||||
// startY: Page coordinates of pointer at movestart.
|
||||
// distX:
|
||||
// distY: Distance the pointer has moved since movestart.
|
||||
// deltaX:
|
||||
// deltaY: Distance the finger has moved since last event.
|
||||
// velocityX:
|
||||
// velocityY: Average velocity over last few events.
|
||||
|
||||
|
||||
(function (module) { |
||||
if (typeof define === 'function' && define.amd) { |
||||
// AMD. Register as an anonymous module.
|
||||
define(['jquery'], module); |
||||
} else { |
||||
// Browser globals
|
||||
module(jQuery); |
||||
} |
||||
})(function(jQuery, undefined){ |
||||
|
||||
var // Number of pixels a pressed pointer travels before movestart
|
||||
// event is fired.
|
||||
threshold = 6, |
||||
|
||||
add = jQuery.event.add, |
||||
|
||||
remove = jQuery.event.remove, |
||||
|
||||
// Just sugar, so we can have arguments in the same order as
|
||||
// add and remove.
|
||||
trigger = function(node, type, data) { |
||||
jQuery.event.trigger(type, data, node); |
||||
}, |
||||
|
||||
// Shim for requestAnimationFrame, falling back to timer. See:
|
||||
// see http://paulirish.com/2011/requestanimationframe-for-smart-animating/
|
||||
requestFrame = (function(){ |
||||
return ( |
||||
window.requestAnimationFrame || |
||||
window.webkitRequestAnimationFrame || |
||||
window.mozRequestAnimationFrame || |
||||
window.oRequestAnimationFrame || |
||||
window.msRequestAnimationFrame || |
||||
function(fn, element){ |
||||
return window.setTimeout(function(){ |
||||
fn(); |
||||
}, 25); |
||||
} |
||||
); |
||||
})(), |
||||
|
||||
ignoreTags = { |
||||
textarea: true, |
||||
input: true, |
||||
select: true, |
||||
button: true |
||||
}, |
||||
|
||||
mouseevents = { |
||||
move: 'mousemove', |
||||
cancel: 'mouseup dragstart', |
||||
end: 'mouseup' |
||||
}, |
||||
|
||||
touchevents = { |
||||
move: 'touchmove', |
||||
cancel: 'touchend', |
||||
end: 'touchend' |
||||
}; |
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
function Timer(fn){ |
||||
var callback = fn, |
||||
active = false, |
||||
running = false; |
||||
|
||||
function trigger(time) { |
||||
if (active){ |
||||
callback(); |
||||
requestFrame(trigger); |
||||
running = true; |
||||
active = false; |
||||
} |
||||
else { |
||||
running = false; |
||||
} |
||||
} |
||||
|
||||
this.kick = function(fn) { |
||||
active = true; |
||||
if (!running) { trigger(); } |
||||
}; |
||||
|
||||
this.end = function(fn) { |
||||
var cb = callback; |
||||
|
||||
if (!fn) { return; } |
||||
|
||||
// If the timer is not running, simply call the end callback.
|
||||
if (!running) { |
||||
fn(); |
||||
} |
||||
// If the timer is running, and has been kicked lately, then
|
||||
// queue up the current callback and the end callback, otherwise
|
||||
// just the end callback.
|
||||
else { |
||||
callback = active ? |
||||
function(){ cb(); fn(); } :
|
||||
fn ; |
||||
|
||||
active = true; |
||||
} |
||||
}; |
||||
} |
||||
|
||||
|
||||
// Functions
|
||||
|
||||
function returnTrue() { |
||||
return true; |
||||
} |
||||
|
||||
function returnFalse() { |
||||
return false; |
||||
} |
||||
|
||||
function preventDefault(e) { |
||||
e.preventDefault(); |
||||
} |
||||
|
||||
function preventIgnoreTags(e) { |
||||
// Don't prevent interaction with form elements.
|
||||
if (ignoreTags[ e.target.tagName.toLowerCase() ]) { return; } |
||||
|
||||
e.preventDefault(); |
||||
} |
||||
|
||||
function isLeftButton(e) { |
||||
// Ignore mousedowns on any button other than the left (or primary)
|
||||
// mouse button, or when a modifier key is pressed.
|
||||
return (e.which === 1 && !e.ctrlKey && !e.altKey); |
||||
} |
||||
|
||||
function identifiedTouch(touchList, id) { |
||||
var i, l; |
||||
|
||||
if (touchList.identifiedTouch) { |
||||
return touchList.identifiedTouch(id); |
||||
} |
||||
|
||||
// touchList.identifiedTouch() does not exist in
|
||||
// webkit yet… we must do the search ourselves...
|
||||
|
||||
i = -1; |
||||
l = touchList.length; |
||||
|
||||
while (++i < l) { |
||||
if (touchList[i].identifier === id) { |
||||
return touchList[i]; |
||||
} |
||||
} |
||||
} |
||||
|
||||
function changedTouch(e, event) { |
||||
var touch = identifiedTouch(e.changedTouches, event.identifier); |
||||
|
||||
// This isn't the touch you're looking for.
|
||||
if (!touch) { return; } |
||||
|
||||
// Chrome Android (at least) includes touches that have not
|
||||
// changed in e.changedTouches. That's a bit annoying. Check
|
||||
// that this touch has changed.
|
||||
if (touch.pageX === event.pageX && touch.pageY === event.pageY) { return; } |
||||
|
||||
return touch; |
||||
} |
||||
|
||||
|
||||
// Handlers that decide when the first movestart is triggered
|
||||
|
||||
function mousedown(e){ |
||||
var data; |
||||
|
||||
if (!isLeftButton(e)) { return; } |
||||
|
||||
data = { |
||||
target: e.target, |
||||
startX: e.pageX, |
||||
startY: e.pageY, |
||||
timeStamp: e.timeStamp |
||||
}; |
||||
|
||||
add(document, mouseevents.move, mousemove, data); |
||||
add(document, mouseevents.cancel, mouseend, data); |
||||
} |
||||
|
||||
function mousemove(e){ |
||||
var data = e.data; |
||||
|
||||
checkThreshold(e, data, e, removeMouse); |
||||
} |
||||
|
||||
function mouseend(e) { |
||||
removeMouse(); |
||||
} |
||||
|
||||
function removeMouse() { |
||||
remove(document, mouseevents.move, mousemove); |
||||
remove(document, mouseevents.cancel, mouseend); |
||||
} |
||||
|
||||
function touchstart(e) { |
||||
var touch, template; |
||||
|
||||
// Don't get in the way of interaction with form elements.
|
||||
if (ignoreTags[ e.target.tagName.toLowerCase() ]) { return; } |
||||
|
||||
touch = e.changedTouches[0]; |
||||
|
||||
// iOS live updates the touch objects whereas Android gives us copies.
|
||||
// That means we can't trust the touchstart object to stay the same,
|
||||
// so we must copy the data. This object acts as a template for
|
||||
// movestart, move and moveend event objects.
|
||||
template = { |
||||
target: touch.target, |
||||
startX: touch.pageX, |
||||
startY: touch.pageY, |
||||
timeStamp: e.timeStamp, |
||||
identifier: touch.identifier |
||||
}; |
||||
|
||||
// Use the touch identifier as a namespace, so that we can later
|
||||
// remove handlers pertaining only to this touch.
|
||||
add(document, touchevents.move + '.' + touch.identifier, touchmove, template); |
||||
add(document, touchevents.cancel + '.' + touch.identifier, touchend, template); |
||||
} |
||||
|
||||
function touchmove(e){ |
||||
var data = e.data, |
||||
touch = changedTouch(e, data); |
||||
|
||||
if (!touch) { return; } |
||||
|
||||
checkThreshold(e, data, touch, removeTouch); |
||||
} |
||||
|
||||
function touchend(e) { |
||||
var template = e.data, |
||||
touch = identifiedTouch(e.changedTouches, template.identifier); |
||||
|
||||
if (!touch) { return; } |
||||
|
||||
removeTouch(template.identifier); |
||||
} |
||||
|
||||
function removeTouch(identifier) { |
||||
remove(document, '.' + identifier, touchmove); |
||||
remove(document, '.' + identifier, touchend); |
||||
} |
||||
|
||||
|
||||
// Logic for deciding when to trigger a movestart.
|
||||
|
||||
function checkThreshold(e, template, touch, fn) { |
||||
var distX = touch.pageX - template.startX, |
||||
distY = touch.pageY - template.startY; |
||||
|
||||
// Do nothing if the threshold has not been crossed.
|
||||
if ((distX * distX) + (distY * distY) < (threshold * threshold)) { return; } |
||||
|
||||
triggerStart(e, template, touch, distX, distY, fn); |
||||
} |
||||
|
||||
function handled() { |
||||
// this._handled should return false once, and after return true.
|
||||
this._handled = returnTrue; |
||||
return false; |
||||
} |
||||
|
||||
function flagAsHandled(e) { |
||||
e._handled(); |
||||
} |
||||
|
||||
function triggerStart(e, template, touch, distX, distY, fn) { |
||||
var node = template.target, |
||||
touches, time; |
||||
|
||||
touches = e.targetTouches; |
||||
time = e.timeStamp - template.timeStamp; |
||||
|
||||
// Create a movestart object with some special properties that
|
||||
// are passed only to the movestart handlers.
|
||||
template.type = 'movestart'; |
||||
template.distX = distX; |
||||
template.distY = distY; |
||||
template.deltaX = distX; |
||||
template.deltaY = distY; |
||||
template.pageX = touch.pageX; |
||||
template.pageY = touch.pageY; |
||||
template.velocityX = distX / time; |
||||
template.velocityY = distY / time; |
||||
template.targetTouches = touches; |
||||
template.finger = touches ? |
||||
touches.length : |
||||
1 ; |
||||
|
||||
// The _handled method is fired to tell the default movestart
|
||||
// handler that one of the move events is bound.
|
||||
template._handled = handled; |
||||
|
||||
// Pass the touchmove event so it can be prevented if or when
|
||||
// movestart is handled.
|
||||
template._preventTouchmoveDefault = function() { |
||||
e.preventDefault(); |
||||
}; |
||||
|
||||
// Trigger the movestart event.
|
||||
trigger(template.target, template); |
||||
|
||||
// Unbind handlers that tracked the touch or mouse up till now.
|
||||
fn(template.identifier); |
||||
} |
||||
|
||||
|
||||
// Handlers that control what happens following a movestart
|
||||
|
||||
function activeMousemove(e) { |
||||
var timer = e.data.timer; |
||||
|
||||
e.data.touch = e; |
||||
e.data.timeStamp = e.timeStamp; |
||||
timer.kick(); |
||||
} |
||||
|
||||
function activeMouseend(e) { |
||||
var event = e.data.event, |
||||
timer = e.data.timer; |
||||
|
||||
removeActiveMouse(); |
||||
|
||||
endEvent(event, timer, function() { |
||||
// Unbind the click suppressor, waiting until after mouseup
|
||||
// has been handled.
|
||||
setTimeout(function(){ |
||||
remove(event.target, 'click', returnFalse); |
||||
}, 0); |
||||
}); |
||||
} |
||||
|
||||
function removeActiveMouse(event) { |
||||
remove(document, mouseevents.move, activeMousemove); |
||||
remove(document, mouseevents.end, activeMouseend); |
||||
} |
||||
|
||||
function activeTouchmove(e) { |
||||
var event = e.data.event, |
||||
timer = e.data.timer, |
||||
touch = changedTouch(e, event); |
||||
|
||||
if (!touch) { return; } |
||||
|
||||
// Stop the interface from gesturing
|
||||
e.preventDefault(); |
||||
|
||||
event.targetTouches = e.targetTouches; |
||||
e.data.touch = touch; |
||||
e.data.timeStamp = e.timeStamp; |
||||
timer.kick(); |
||||
} |
||||
|
||||
function activeTouchend(e) { |
||||
var event = e.data.event, |
||||
timer = e.data.timer, |
||||
touch = identifiedTouch(e.changedTouches, event.identifier); |
||||
|
||||
// This isn't the touch you're looking for.
|
||||
if (!touch) { return; } |
||||
|
||||
removeActiveTouch(event); |
||||
endEvent(event, timer); |
||||
} |
||||
|
||||
function removeActiveTouch(event) { |
||||
remove(document, '.' + event.identifier, activeTouchmove); |
||||
remove(document, '.' + event.identifier, activeTouchend); |
||||
} |
||||
|
||||
|
||||
// Logic for triggering move and moveend events
|
||||
|
||||
function updateEvent(event, touch, timeStamp, timer) { |
||||
var time = timeStamp - event.timeStamp; |
||||
|
||||
event.type = 'move'; |
||||
event.distX = touch.pageX - event.startX; |
||||
event.distY = touch.pageY - event.startY; |
||||
event.deltaX = touch.pageX - event.pageX; |
||||
event.deltaY = touch.pageY - event.pageY; |
||||
|
||||
// Average the velocity of the last few events using a decay
|
||||
// curve to even out spurious jumps in values.
|
||||
event.velocityX = 0.3 * event.velocityX + 0.7 * event.deltaX / time; |
||||
event.velocityY = 0.3 * event.velocityY + 0.7 * event.deltaY / time; |
||||
event.pageX = touch.pageX; |
||||
event.pageY = touch.pageY; |
||||
} |
||||
|
||||
function endEvent(event, timer, fn) { |
||||
timer.end(function(){ |
||||
event.type = 'moveend'; |
||||
|
||||
trigger(event.target, event); |
||||
|
||||
return fn && fn(); |
||||
}); |
||||
} |
||||
|
||||
|
||||
// jQuery special event definition
|
||||
|
||||
function setup(data, namespaces, eventHandle) { |
||||
// Stop the node from being dragged
|
||||
//add(this, 'dragstart.move drag.move', preventDefault);
|
||||
|
||||
// Prevent text selection and touch interface scrolling
|
||||
//add(this, 'mousedown.move', preventIgnoreTags);
|
||||
|
||||
// Tell movestart default handler that we've handled this
|
||||
add(this, 'movestart.move', flagAsHandled); |
||||
|
||||
// Don't bind to the DOM. For speed.
|
||||
return true; |
||||
} |
||||
|
||||
function teardown(namespaces) { |
||||
remove(this, 'dragstart drag', preventDefault); |
||||
remove(this, 'mousedown touchstart', preventIgnoreTags); |
||||
remove(this, 'movestart', flagAsHandled); |
||||
|
||||
// Don't bind to the DOM. For speed.
|
||||
return true; |
||||
} |
||||
|
||||
function addMethod(handleObj) { |
||||
// We're not interested in preventing defaults for handlers that
|
||||
// come from internal move or moveend bindings
|
||||
if (handleObj.namespace === "move" || handleObj.namespace === "moveend") { |
||||
return; |
||||
} |
||||
|
||||
// Stop the node from being dragged
|
||||
add(this, 'dragstart.' + handleObj.guid + ' drag.' + handleObj.guid, preventDefault, undefined, handleObj.selector); |
||||
|
||||
// Prevent text selection and touch interface scrolling
|
||||
add(this, 'mousedown.' + handleObj.guid, preventIgnoreTags, undefined, handleObj.selector); |
||||
} |
||||
|
||||
function removeMethod(handleObj) { |
||||
if (handleObj.namespace === "move" || handleObj.namespace === "moveend") { |
||||
return; |
||||
} |
||||
|
||||
remove(this, 'dragstart.' + handleObj.guid + ' drag.' + handleObj.guid); |
||||
remove(this, 'mousedown.' + handleObj.guid); |
||||
} |
||||
|
||||
jQuery.event.special.movestart = { |
||||
setup: setup, |
||||
teardown: teardown, |
||||
add: addMethod, |
||||
remove: removeMethod, |
||||
|
||||
_default: function(e) { |
||||
var event, data; |
||||
|
||||
// If no move events were bound to any ancestors of this
|
||||
// target, high tail it out of here.
|
||||
if (!e._handled()) { return; } |
||||
|
||||
function update(time) { |
||||
updateEvent(event, data.touch, data.timeStamp); |
||||
trigger(e.target, event); |
||||
} |
||||
|
||||
event = { |
||||
target: e.target, |
||||
startX: e.startX, |
||||
startY: e.startY, |
||||
pageX: e.pageX, |
||||
pageY: e.pageY, |
||||
distX: e.distX, |
||||
distY: e.distY, |
||||
deltaX: e.deltaX, |
||||
deltaY: e.deltaY, |
||||
velocityX: e.velocityX, |
||||
velocityY: e.velocityY, |
||||
timeStamp: e.timeStamp, |
||||
identifier: e.identifier, |
||||
targetTouches: e.targetTouches, |
||||
finger: e.finger |
||||
}; |
||||
|
||||
data = { |
||||
event: event, |
||||
timer: new Timer(update), |
||||
touch: undefined, |
||||
timeStamp: undefined |
||||
}; |
||||
|
||||
if (e.identifier === undefined) { |
||||
// We're dealing with a mouse
|
||||
// Stop clicks from propagating during a move
|
||||
add(e.target, 'click', returnFalse); |
||||
add(document, mouseevents.move, activeMousemove, data); |
||||
add(document, mouseevents.end, activeMouseend, data); |
||||
} |
||||
else { |
||||
// We're dealing with a touch. Stop touchmove doing
|
||||
// anything defaulty.
|
||||
e._preventTouchmoveDefault(); |
||||
add(document, touchevents.move + '.' + e.identifier, activeTouchmove, data); |
||||
add(document, touchevents.end + '.' + e.identifier, activeTouchend, data); |
||||
} |
||||
} |
||||
}; |
||||
|
||||
jQuery.event.special.move = { |
||||
setup: function() { |
||||
// Bind a noop to movestart. Why? It's the movestart
|
||||
// setup that decides whether other move events are fired.
|
||||
add(this, 'movestart.move', jQuery.noop); |
||||
}, |
||||
|
||||
teardown: function() { |
||||
remove(this, 'movestart.move', jQuery.noop); |
||||
} |
||||
}; |
||||
|
||||
jQuery.event.special.moveend = { |
||||
setup: function() { |
||||
// Bind a noop to movestart. Why? It's the movestart
|
||||
// setup that decides whether other move events are fired.
|
||||
add(this, 'movestart.moveend', jQuery.noop); |
||||
}, |
||||
|
||||
teardown: function() { |
||||
remove(this, 'movestart.moveend', jQuery.noop); |
||||
} |
||||
}; |
||||
|
||||
add(document, 'mousedown.move', mousedown); |
||||
add(document, 'touchstart.move', touchstart); |
||||
|
||||
// Make jQuery copy touch event properties over to the jQuery event
|
||||
// object, if they are not already listed. But only do the ones we
|
||||
// really need. IE7/8 do not have Array#indexOf(), but nor do they
|
||||
// have touch events, so let's assume we can ignore them.
|
||||
if (typeof Array.prototype.indexOf === 'function') { |
||||
(function(jQuery, undefined){ |
||||
var props = ["changedTouches", "targetTouches"], |
||||
l = props.length; |
||||
|
||||
while (l--) { |
||||
if (jQuery.event.props.indexOf(props[l]) === -1) { |
||||
jQuery.event.props.push(props[l]); |
||||
} |
||||
} |
||||
})(jQuery); |
||||
}; |
||||
}); |
@ -0,0 +1,103 @@
|
||||
(function($){ |
||||
|
||||
$.fn.twentytwenty = function(options) { |
||||
var options = $.extend({default_offset_pct: 0.5, orientation: 'horizontal'}, options); |
||||
return this.each(function() { |
||||
|
||||
var sliderPct = options.default_offset_pct; |
||||
var container = $(this); |
||||
var sliderOrientation = options.orientation; |
||||
var beforeDirection = (sliderOrientation === 'vertical') ? 'down' : 'left'; |
||||
var afterDirection = (sliderOrientation === 'vertical') ? 'up' : 'right'; |
||||
|
||||
|
||||
container.wrap("<div class='twentytwenty-wrapper twentytwenty-" + sliderOrientation + "'></div>"); |
||||
container.append("<div class='twentytwenty-overlay'></div>"); |
||||
var beforeImg = container.find("img:first"); |
||||
var afterImg = container.find("img:last"); |
||||
container.append("<div class='twentytwenty-handle'></div>"); |
||||
var slider = container.find(".twentytwenty-handle"); |
||||
slider.append("<span class='twentytwenty-" + beforeDirection + "-arrow'></span>"); |
||||
slider.append("<span class='twentytwenty-" + afterDirection + "-arrow'></span>"); |
||||
container.addClass("twentytwenty-container"); |
||||
beforeImg.addClass("twentytwenty-before"); |
||||
afterImg.addClass("twentytwenty-after"); |
||||
|
||||
var overlay = container.find(".twentytwenty-overlay"); |
||||
overlay.append("<div class='twentytwenty-before-label'></div>"); |
||||
overlay.append("<div class='twentytwenty-after-label'></div>"); |
||||
|
||||
var calcOffset = function(dimensionPct) { |
||||
var w = beforeImg.width(); |
||||
var h = beforeImg.height(); |
||||
return { |
||||
w: w+"px", |
||||
h: h+"px", |
||||
cw: (dimensionPct*w)+"px", |
||||
ch: (dimensionPct*h)+"px" |
||||
}; |
||||
}; |
||||
|
||||
var adjustContainer = function(offset) { |
||||
if (sliderOrientation === 'vertical') { |
||||
beforeImg.css("clip", "rect(0,"+offset.w+","+offset.ch+",0)"); |
||||
} |
||||
else { |
||||
beforeImg.css("clip", "rect(0,"+offset.cw+","+offset.h+",0)"); |
||||
} |
||||
container.css("height", offset.h); |
||||
}; |
||||
|
||||
var adjustSlider = function(pct) { |
||||
var offset = calcOffset(pct); |
||||
slider.css((sliderOrientation==="vertical") ? "top" : "left", (sliderOrientation==="vertical") ? offset.ch : offset.cw); |
||||
adjustContainer(offset); |
||||
} |
||||
|
||||
$(window).on("resize.twentytwenty", function(e) { |
||||
adjustSlider(sliderPct); |
||||
}); |
||||
|
||||
var offsetX = 0; |
||||
var imgWidth = 0; |
||||
|
||||
slider.on("movestart", function(e) { |
||||
if (((e.distX > e.distY && e.distX < -e.distY) || (e.distX < e.distY && e.distX > -e.distY)) && sliderOrientation !== 'vertical') { |
||||
e.preventDefault(); |
||||
} |
||||
else if (((e.distX < e.distY && e.distX < -e.distY) || (e.distX > e.distY && e.distX > -e.distY)) && sliderOrientation === 'vertical') { |
||||
e.preventDefault(); |
||||
} |
||||
container.addClass("active"); |
||||
offsetX = container.offset().left; |
||||
offsetY = container.offset().top; |
||||
imgWidth = beforeImg.width();
|
||||
imgHeight = beforeImg.height();
|
||||
}); |
||||
|
||||
slider.on("moveend", function(e) { |
||||
container.removeClass("active"); |
||||
}); |
||||
|
||||
slider.on("move", function(e) { |
||||
if (container.hasClass("active")) { |
||||
sliderPct = (sliderOrientation === 'vertical') ? (e.pageY-offsetY)/imgHeight : (e.pageX-offsetX)/imgWidth; |
||||
if (sliderPct < 0) { |
||||
sliderPct = 0; |
||||
} |
||||
if (sliderPct > 1) { |
||||
sliderPct = 1; |
||||
} |
||||
adjustSlider(sliderPct); |
||||
} |
||||
}); |
||||
|
||||
container.find("img").on("mousedown", function(event) { |
||||
event.preventDefault(); |
||||
}); |
||||
|
||||
$(window).trigger("resize.twentytwenty"); |
||||
}); |
||||
}; |
||||
|
||||
})(jQuery); |
@ -0,0 +1,205 @@
|
||||
.twentytwenty-horizontal .twentytwenty-handle:before, .twentytwenty-horizontal .twentytwenty-handle:after, .twentytwenty-vertical .twentytwenty-handle:before, .twentytwenty-vertical .twentytwenty-handle:after { |
||||
content: " "; |
||||
display: block; |
||||
background: white; |
||||
position: absolute; |
||||
z-index: 30; |
||||
-webkit-box-shadow: 0px 0px 12px rgba(51, 51, 51, 0.5); |
||||
-moz-box-shadow: 0px 0px 12px rgba(51, 51, 51, 0.5); |
||||
box-shadow: 0px 0px 12px rgba(51, 51, 51, 0.5); } |
||||
|
||||
.twentytwenty-horizontal .twentytwenty-handle:before, .twentytwenty-horizontal .twentytwenty-handle:after { |
||||
width: 3px; |
||||
height: 9999px; |
||||
left: 50%; |
||||
margin-left: -1.5px; } |
||||
|
||||
.twentytwenty-vertical .twentytwenty-handle:before, .twentytwenty-vertical .twentytwenty-handle:after { |
||||
width: 9999px; |
||||
height: 3px; |
||||
top: 50%; |
||||
margin-top: -1.5px; } |
||||
|
||||
.twentytwenty-before-label, .twentytwenty-after-label, .twentytwenty-overlay { |
||||
position: absolute; |
||||
top: 0; |
||||
width: 100%; |
||||
height: 100%; } |
||||
|
||||
.twentytwenty-before-label, .twentytwenty-after-label, .twentytwenty-overlay { |
||||
-webkit-transition-duration: 0.5s; |
||||
-moz-transition-duration: 0.5s; |
||||
transition-duration: 0.5s; } |
||||
|
||||
.twentytwenty-before-label, .twentytwenty-after-label { |
||||
-webkit-transition-property: opacity; |
||||
-moz-transition-property: opacity; |
||||
transition-property: opacity; } |
||||
|
||||
.twentytwenty-before-label:before, .twentytwenty-after-label:before { |
||||
color: white; |
||||
font-size: 13px; |
||||
letter-spacing: 0.1em; } |
||||
|
||||
.twentytwenty-before-label:before, .twentytwenty-after-label:before { |
||||
position: absolute; |
||||
background: rgba(255, 255, 255, 0.2); |
||||
line-height: 38px; |
||||
padding: 0 20px; |
||||
-webkit-border-radius: 2px; |
||||
-moz-border-radius: 2px; |
||||
border-radius: 2px; } |
||||
|
||||
.twentytwenty-horizontal .twentytwenty-before-label:before, .twentytwenty-horizontal .twentytwenty-after-label:before { |
||||
top: 50%; |
||||
margin-top: -19px; } |
||||
|
||||
.twentytwenty-vertical .twentytwenty-before-label:before, .twentytwenty-vertical .twentytwenty-after-label:before { |
||||
left: 50%; |
||||
margin-left: -45px; |
||||
text-align: center; |
||||
width: 90px; } |
||||
|
||||
.twentytwenty-left-arrow, .twentytwenty-right-arrow, .twentytwenty-up-arrow, .twentytwenty-down-arrow { |
||||
width: 0; |
||||
height: 0; |
||||
border: 6px inset transparent; |
||||
position: absolute; } |
||||
|
||||
.twentytwenty-left-arrow, .twentytwenty-right-arrow { |
||||
top: 50%; |
||||
margin-top: -6px; } |
||||
|
||||
.twentytwenty-up-arrow, .twentytwenty-down-arrow { |
||||
left: 50%; |
||||
margin-left: -6px; } |
||||
|
||||
.twentytwenty-container { |
||||
-webkit-box-sizing: content-box; |
||||
-moz-box-sizing: content-box; |
||||
box-sizing: content-box; |
||||
z-index: 0; |
||||
overflow: hidden; |
||||
position: relative; |
||||
-webkit-user-select: none; |
||||
-moz-user-select: none; } |
||||
.twentytwenty-container img { |
||||
max-width: 100%; |
||||
position: absolute; |
||||
top: 0; |
||||
display: block; } |
||||
.twentytwenty-container.active .twentytwenty-overlay, .twentytwenty-container.active :hover.twentytwenty-overlay { |
||||
background: rgba(0, 0, 0, 0); } |
||||
.twentytwenty-container.active .twentytwenty-overlay .twentytwenty-before-label, |
||||
.twentytwenty-container.active .twentytwenty-overlay .twentytwenty-after-label, .twentytwenty-container.active :hover.twentytwenty-overlay .twentytwenty-before-label, |
||||
.twentytwenty-container.active :hover.twentytwenty-overlay .twentytwenty-after-label { |
||||
opacity: 0; } |
||||
.twentytwenty-container * { |
||||
-webkit-box-sizing: content-box; |
||||
-moz-box-sizing: content-box; |
||||
box-sizing: content-box; } |
||||
|
||||
.twentytwenty-before-label { |
||||
opacity: 0; } |
||||
.twentytwenty-before-label:before { |
||||
content: "Screen Off"; } |
||||
|
||||
.twentytwenty-after-label { |
||||
opacity: 0; } |
||||
.twentytwenty-after-label:before { |
||||
content: "Screen On"; } |
||||
|
||||
.twentytwenty-horizontal .twentytwenty-before-label:before { |
||||
left: 10px; } |
||||
|
||||
.twentytwenty-horizontal .twentytwenty-after-label:before { |
||||
right: 10px; } |
||||
|
||||
.twentytwenty-vertical .twentytwenty-before-label:before { |
||||
top: 10px; } |
||||
|
||||
.twentytwenty-vertical .twentytwenty-after-label:before { |
||||
bottom: 10px; } |
||||
|
||||
.twentytwenty-overlay { |
||||
-webkit-transition-property: background; |
||||
-moz-transition-property: background; |
||||
transition-property: background; |
||||
background: rgba(0, 0, 0, 0); |
||||
z-index: 25; } |
||||
.twentytwenty-overlay:hover { |
||||
background: rgba(0, 0, 0, 0.5); } |
||||
.twentytwenty-overlay:hover .twentytwenty-after-label { |
||||
opacity: 1; } |
||||
.twentytwenty-overlay:hover .twentytwenty-before-label { |
||||
opacity: 1; } |
||||
|
||||
.twentytwenty-before { |
||||
z-index: 20; } |
||||
|
||||
.twentytwenty-after { |
||||
z-index: 10; } |
||||
|
||||
.twentytwenty-handle { |
||||
height: 38px; |
||||
width: 38px; |
||||
position: absolute; |
||||
left: 50%; |
||||
top: 50%; |
||||
margin-left: -22px; |
||||
margin-top: -22px; |
||||
border: 3px solid white; |
||||
-webkit-border-radius: 1000px; |
||||
-moz-border-radius: 1000px; |
||||
border-radius: 1000px; |
||||
-webkit-box-shadow: 0px 0px 12px rgba(51, 51, 51, 0.5); |
||||
-moz-box-shadow: 0px 0px 12px rgba(51, 51, 51, 0.5); |
||||
box-shadow: 0px 0px 12px rgba(51, 51, 51, 0.5); |
||||
z-index: 40; |
||||
cursor: pointer; } |
||||
|
||||
.twentytwenty-horizontal .twentytwenty-handle:before { |
||||
bottom: 50%; |
||||
margin-bottom: 22px; |
||||
-webkit-box-shadow: 0 3px 0 white, 0px 0px 12px rgba(51, 51, 51, 0.5); |
||||
-moz-box-shadow: 0 3px 0 white, 0px 0px 12px rgba(51, 51, 51, 0.5); |
||||
box-shadow: 0 3px 0 white, 0px 0px 12px rgba(51, 51, 51, 0.5); } |
||||
.twentytwenty-horizontal .twentytwenty-handle:after { |
||||
top: 50%; |
||||
margin-top: 22px; |
||||
-webkit-box-shadow: 0 -3px 0 white, 0px 0px 12px rgba(51, 51, 51, 0.5); |
||||
-moz-box-shadow: 0 -3px 0 white, 0px 0px 12px rgba(51, 51, 51, 0.5); |
||||
box-shadow: 0 -3px 0 white, 0px 0px 12px rgba(51, 51, 51, 0.5); } |
||||
|
||||
.twentytwenty-vertical .twentytwenty-handle:before { |
||||
left: 50%; |
||||
margin-left: 22px; |
||||
-webkit-box-shadow: 3px 0 0 white, 0px 0px 12px rgba(51, 51, 51, 0.5); |
||||
-moz-box-shadow: 3px 0 0 white, 0px 0px 12px rgba(51, 51, 51, 0.5); |
||||
box-shadow: 3px 0 0 white, 0px 0px 12px rgba(51, 51, 51, 0.5); } |
||||
.twentytwenty-vertical .twentytwenty-handle:after { |
||||
right: 50%; |
||||
margin-right: 22px; |
||||
-webkit-box-shadow: -3px 0 0 white, 0px 0px 12px rgba(51, 51, 51, 0.5); |
||||
-moz-box-shadow: -3px 0 0 white, 0px 0px 12px rgba(51, 51, 51, 0.5); |
||||
box-shadow: -3px 0 0 white, 0px 0px 12px rgba(51, 51, 51, 0.5); } |
||||
|
||||
.twentytwenty-left-arrow { |
||||
border-right: 6px solid white; |
||||
left: 50%; |
||||
margin-left: -17px; } |
||||
|
||||
.twentytwenty-right-arrow { |
||||
border-left: 6px solid white; |
||||
right: 50%; |
||||
margin-right: -17px; } |
||||
|
||||
.twentytwenty-up-arrow { |
||||
border-bottom: 6px solid white; |
||||
top: 50%; |
||||
margin-top: -17px; } |
||||
|
||||
.twentytwenty-down-arrow { |
||||
border-top: 6px solid white; |
||||
bottom: 50%; |
||||
margin-bottom: -17px; } |
After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 389 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 373 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 226 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 160 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 297 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 470 KiB |
After Width: | Height: | Size: 85 KiB |
After Width: | Height: | Size: 613 KiB |
After Width: | Height: | Size: 77 KiB |
After Width: | Height: | Size: 416 KiB |
After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 418 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 199 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 186 KiB |