mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-12-21 10:41:39 +00:00
experementing with css scale, origin and translate...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
9317ea0566
commit
efcbea5b18
183
ui (gen4)/experiments/scale-origin.html
Executable file
183
ui (gen4)/experiments/scale-origin.html
Executable file
@ -0,0 +1,183 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<style>
|
||||||
|
|
||||||
|
.container {
|
||||||
|
position: absolute;
|
||||||
|
top: 200px;
|
||||||
|
left: 400px;
|
||||||
|
width: 400px;
|
||||||
|
height: 400px;
|
||||||
|
border: dashed 1px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-center {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
|
||||||
|
border-top: solid 1px black;
|
||||||
|
border-left: solid 1px black;
|
||||||
|
}
|
||||||
|
.container-center:after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: -11px;
|
||||||
|
left: -11px;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
|
||||||
|
border-top: none;
|
||||||
|
border-left: none;
|
||||||
|
border-bottom: solid 1px black;
|
||||||
|
border-right: solid 1px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block {
|
||||||
|
position: absolute;
|
||||||
|
top: auto;
|
||||||
|
left: auto;
|
||||||
|
width: 300px;
|
||||||
|
height: 300px;
|
||||||
|
background: silver;
|
||||||
|
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.point, .point-old {
|
||||||
|
position: absolute;
|
||||||
|
width: 4px;
|
||||||
|
height: 4px;
|
||||||
|
border: solid 1px blue;
|
||||||
|
margin-top: -2px;
|
||||||
|
margin-left: -2px;
|
||||||
|
|
||||||
|
transition-origin: 50% 50%;
|
||||||
|
}
|
||||||
|
.point-old {
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block, .point {
|
||||||
|
-webkit-transition: all 0.2s linear;
|
||||||
|
-moz-transition: all 0.2s linear;
|
||||||
|
transition: all 0.2s linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script src="../ext-lib/jquery.js"></script>
|
||||||
|
<script src="../ext-lib/jquery-ui.js"></script>
|
||||||
|
|
||||||
|
<script src="../lib/jli.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
function setOffset(l, t){
|
||||||
|
setElementOffset($('.block'), l, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
function setScale(s){
|
||||||
|
setElementScale($('.block'), s)
|
||||||
|
setElementScale($('.point'), 1/s)
|
||||||
|
setElementScale($('.point-old'), 1/s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The goal of the experiment is to make this do it's thing without
|
||||||
|
// changing element's screen position
|
||||||
|
//
|
||||||
|
// XXX this does not work of position is negative...
|
||||||
|
function setOrigin(l, t, no_comp){
|
||||||
|
var block = $('.block')
|
||||||
|
var o = getElementOrigin(block)
|
||||||
|
|
||||||
|
if(!no_comp){
|
||||||
|
var s = getElementScale(block)
|
||||||
|
|
||||||
|
var offset = getElementOffset(block)
|
||||||
|
|
||||||
|
// calculate the offset change and compensate...
|
||||||
|
// XXX this breaks with negative values...
|
||||||
|
// - starts moving around
|
||||||
|
// - the secondary pointer goes crazy...
|
||||||
|
var cl = offset.left + ((o.left - o.left*s) - (l - l*s))
|
||||||
|
var ct = offset.top + ((o.top - o.top*s) - (t - t*s))
|
||||||
|
|
||||||
|
setElementOffset(block, cl, ct)
|
||||||
|
}
|
||||||
|
|
||||||
|
setElementOrigin(block, l+'px', t+'px')
|
||||||
|
|
||||||
|
setElementOffset($('.point'), l, t)
|
||||||
|
setElementOffset($('.point-old'), o.left, o.top)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// center a specific point (default: origin)
|
||||||
|
//
|
||||||
|
// NOTE: scale indicates the source coordinate scale, if set to 1 t and
|
||||||
|
// l will 1:1 to screen, and if set the the same scale as the element
|
||||||
|
// then t and l will be 1:1 to the element...
|
||||||
|
// supported keywords:
|
||||||
|
// 'screen'
|
||||||
|
// 'elem'
|
||||||
|
function centerBlock(l, t, scale){
|
||||||
|
scale = scale == true || scale == 'screen' ? 1
|
||||||
|
: scale == 'elem' ? null
|
||||||
|
: scale
|
||||||
|
|
||||||
|
var s = getElementScale(block)
|
||||||
|
var block = $('.block')
|
||||||
|
var offset = getElementOffset(block)
|
||||||
|
|
||||||
|
var bo = block.offset()
|
||||||
|
var co = $('.container').offset()
|
||||||
|
|
||||||
|
var W = $('.container').width()
|
||||||
|
var H = $('.container').height()
|
||||||
|
|
||||||
|
var o = getElementOrigin(block)
|
||||||
|
|
||||||
|
// normalize the l,t to element scale...
|
||||||
|
if(l != null && t != null){
|
||||||
|
l = scale != null ? (l/s)*scale : l
|
||||||
|
t = scale != null ? (t/s)*scale : t
|
||||||
|
|
||||||
|
var w = block.width()
|
||||||
|
var h = block.height()
|
||||||
|
o = {
|
||||||
|
top: t*s + (h - h*s) / (w / o.left),
|
||||||
|
left: l*s + (w - w*s) / (h / o.left),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var dl = offset.left + (W/2 - offset.left) - o.left
|
||||||
|
var dt = offset.top + (H/2 - offset.top) - o.top
|
||||||
|
|
||||||
|
setOffset(dl, dt)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$(function(){
|
||||||
|
setOrigin(100, 100)
|
||||||
|
setOffset(50, 100)
|
||||||
|
setScale(0.7)
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="block">
|
||||||
|
<div class="point" title="current origin point"> </div>
|
||||||
|
<div class="point-old" title="previous origin point"> </div>
|
||||||
|
</div>
|
||||||
|
<div class="container-center"> </div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
<!-- vim:set ts=4 sw=4 : -->
|
||||||
@ -43,9 +43,9 @@
|
|||||||
|
|
||||||
/* basic animation... */
|
/* basic animation... */
|
||||||
.viewer:not(.no-transitions) .ribbon-set {
|
.viewer:not(.no-transitions) .ribbon-set {
|
||||||
-webkit-transition: all 0.2s ease, transform 0.2s linear;
|
-webkit-transition: all 0.2s ease, transform 0.2s linear/*, transform-origin 0s none*/;
|
||||||
-moz-transition: all 0.2s ease, transform 0.2s linear;
|
-moz-transition: all 0.2s ease, transform 0.2s linear/*, transform-origin 0s none*/;
|
||||||
transition: all 0.2s ease, transform 0.2s linear;
|
transition: all 0.2s ease, transform 0.2s linear/*, transform-origin 0s none*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
.viewer:not(.no-transitions) .ribbon {
|
.viewer:not(.no-transitions) .ribbon {
|
||||||
|
|||||||
@ -509,6 +509,19 @@ function makeCSSVendorAttrGetter(attr, dfl, callback){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var getElementOrigin = makeCSSVendorAttrGetter(
|
||||||
|
'transformOrigin',
|
||||||
|
{top: 0, left: 0},
|
||||||
|
function(data){
|
||||||
|
res = /([0-9.]*(px|%)) ([0-9.]*(px|%))/.exec(data)
|
||||||
|
return {
|
||||||
|
left: res[1].slice(-2) == 'px' ? parseFloat(res[1]) : res[1],
|
||||||
|
top: res[3].slice(-2) == 'px' ? parseFloat(res[3]) : res[3],
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
// Return a scale value for the given element(s).
|
// Return a scale value for the given element(s).
|
||||||
// NOTE: this will only return a single scale value...
|
// NOTE: this will only return a single scale value...
|
||||||
var getElementScale = makeCSSVendorAttrGetter(
|
var getElementScale = makeCSSVendorAttrGetter(
|
||||||
@ -519,7 +532,7 @@ var getElementScale = makeCSSVendorAttrGetter(
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
var getElementShift = makeCSSVendorAttrGetter(
|
var getElementOffset = makeCSSVendorAttrGetter(
|
||||||
'transform',
|
'transform',
|
||||||
{left: 0, top: 0},
|
{left: 0, top: 0},
|
||||||
function(data){
|
function(data){
|
||||||
@ -544,7 +557,7 @@ function setElementTransform(elem, offset, scale, duration){
|
|||||||
var t3d = USE_3D_TRANSFORM ? 'translate3d(0,0,0)' : ''
|
var t3d = USE_3D_TRANSFORM ? 'translate3d(0,0,0)' : ''
|
||||||
|
|
||||||
if(offset == null){
|
if(offset == null){
|
||||||
offset = getElementShift(elem)
|
offset = getElementOffset(elem)
|
||||||
// number -- only the x coord...
|
// number -- only the x coord...
|
||||||
} else if(typeof(offset) == typeof(1)){
|
} else if(typeof(offset) == typeof(1)){
|
||||||
offset = {
|
offset = {
|
||||||
@ -686,7 +699,7 @@ function animateElementTo(elem, to, duration, easing, speed, callback, use_trans
|
|||||||
|
|
||||||
var start = Date.now()
|
var start = Date.now()
|
||||||
var then = start + duration
|
var then = start + duration
|
||||||
var from = getElementShift(elem)
|
var from = getElementOffset(elem)
|
||||||
var cur = {
|
var cur = {
|
||||||
top: from.top,
|
top: from.top,
|
||||||
left: from.left
|
left: from.left
|
||||||
@ -789,6 +802,11 @@ function stopAnimation(elem){
|
|||||||
|
|
||||||
|
|
||||||
// XXX account for other transitions...
|
// XXX account for other transitions...
|
||||||
|
function setElementOffset(elem, l, t){
|
||||||
|
return setElementTransform(elem, [l, t])
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function setElementScale(elem, scale){
|
function setElementScale(elem, scale){
|
||||||
return setElementTransform(elem, null, scale)
|
return setElementTransform(elem, null, scale)
|
||||||
}
|
}
|
||||||
@ -802,11 +820,30 @@ function setElementOrigin(elem, x, y, z){
|
|||||||
|
|
||||||
return $(elem).css({
|
return $(elem).css({
|
||||||
'transform-origin': value,
|
'transform-origin': value,
|
||||||
|
'-o-transform-origin': value,
|
||||||
'-ms-transform-origin': value,
|
'-ms-transform-origin': value,
|
||||||
|
'-moz-transform-origin': value,
|
||||||
'-webkit-transform-origin': value,
|
'-webkit-transform-origin': value,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this is like setElementOrigin(..) but will compensate for element
|
||||||
|
// shift when scaled...
|
||||||
|
// NOTE: this will work only of translate is used for positioning...
|
||||||
|
function shiftOriginTo(elem, l, t){
|
||||||
|
var o = getElementOrigin(elem)
|
||||||
|
var scale = getElementScale(elem)
|
||||||
|
var offset = getElementOffset(elem)
|
||||||
|
|
||||||
|
// calculate the offset change and compensate...
|
||||||
|
var cl = offset.left + ((o.left - o.left*scale) - (l - l*scale))
|
||||||
|
var ct = offset.top + ((o.top - o.top*scale) - (t - t*scale))
|
||||||
|
|
||||||
|
setElementOffset(elem, cl, ct)
|
||||||
|
|
||||||
|
return setElementOrigin(elem, l+'px', t+'px')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function setTransitionEasing(elem, ease){
|
function setTransitionEasing(elem, ease){
|
||||||
if(typeof(ms) == typeof(0)){
|
if(typeof(ms) == typeof(0)){
|
||||||
|
|||||||
@ -256,25 +256,123 @@ module.RibbonsPrototype = {
|
|||||||
// - use translate for placement of the .ribbon-set (prefered)
|
// - use translate for placement of the .ribbon-set (prefered)
|
||||||
// - use an extra eleemnt for positioning and keep the
|
// - use an extra eleemnt for positioning and keep the
|
||||||
// .ribbon-set at (0,0)
|
// .ribbon-set at (0,0)
|
||||||
|
//
|
||||||
|
// XXX do we account vor viewer offset???
|
||||||
setScale: function(scale, t, l){
|
setScale: function(scale, t, l){
|
||||||
var ribbon_set = this.viewer.find('.ribbon-set')
|
var ribbon_set = this.viewer.find('.ribbon-set')
|
||||||
|
|
||||||
var s = this.getScale()
|
var img = t == null ? this.getImage() : t
|
||||||
|
|
||||||
if(t == null){
|
// XXX need to make this sync and not animate...
|
||||||
var img = this.getImage()
|
this.setOrigin(img)
|
||||||
t = img.offset()
|
|
||||||
l = t.left + (img.width()/s)/2
|
setElementScale(ribbon_set, scale)
|
||||||
t = t.top + (img.height()/s)/2
|
return this
|
||||||
|
},
|
||||||
|
|
||||||
|
getOrigin: function(){
|
||||||
|
return getElementOrigin(this.viewer.find('.ribbon-set'))
|
||||||
|
},
|
||||||
|
// Set ribbon set origin...
|
||||||
|
//
|
||||||
|
// Set origin to center of current image
|
||||||
|
// .setOrigin()
|
||||||
|
// -> ribbons
|
||||||
|
//
|
||||||
|
// Set origin to center of elment:
|
||||||
|
// .setOrigin(elem)
|
||||||
|
// -> ribbons
|
||||||
|
//
|
||||||
|
// Set origin to screen coordinates:
|
||||||
|
// .setOrigin(x, y)
|
||||||
|
// -> ribbons
|
||||||
|
//
|
||||||
|
// XXX this appears not to be scale-neutral -- it gets a different
|
||||||
|
// set of numbers in ribbons >0 after doing .centerRibbon(..)
|
||||||
|
// ...but before calling .centerRibbon(..) this does everything
|
||||||
|
// quite correctly...
|
||||||
|
//
|
||||||
|
// ...this mutual dependency between this and .centerRibbon(..)
|
||||||
|
// makes it really hards to find where exactly the problem is...
|
||||||
|
//
|
||||||
|
// XXX should this also update offset????
|
||||||
|
/*
|
||||||
|
setOrigin: function(a, b){
|
||||||
|
var s = this.getScale()
|
||||||
|
var ribbon_set = this.viewer.find('.ribbon-set')
|
||||||
|
|
||||||
|
if(typeof(a) == typeof(123) && typeof(b) == typeof(123)){
|
||||||
|
var t = a
|
||||||
|
var l = b
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if(a == null){
|
||||||
|
var img = this.getImage()
|
||||||
|
} else {
|
||||||
|
var img = this.getImage(a)
|
||||||
|
}
|
||||||
|
var io = img.offset()
|
||||||
|
var vo = this.viewer.offset()
|
||||||
|
|
||||||
|
// get distance from center of image to top left corner of
|
||||||
|
// screen...
|
||||||
|
// NOTE: the result should be scale-neutral.
|
||||||
|
var l = (io.left - vo.left) + (img.width()*s)/2
|
||||||
|
var t = (io.top - vo.top) + (img.height()*s)/2
|
||||||
}
|
}
|
||||||
|
|
||||||
var ro = ribbon_set.offset()
|
var rs = getElementOffset(ribbon_set)
|
||||||
|
|
||||||
|
var ot = t - rs.top
|
||||||
|
var ol = l - rs.left
|
||||||
|
|
||||||
|
var ro = this.getOrigin()
|
||||||
|
|
||||||
|
console.log('### origin:', ol, ot)
|
||||||
|
|
||||||
var ot = t - ro.top
|
|
||||||
var ol = l - ro.left
|
|
||||||
setElementOrigin(ribbon_set, ol+'px', ot+'px')
|
setElementOrigin(ribbon_set, ol+'px', ot+'px')
|
||||||
|
|
||||||
setElementScale(ribbon_set, scale)
|
//setElementOffset(ribbon_set,
|
||||||
|
// rs.left + (ro.left - ro.left*s) - (l - l*s),
|
||||||
|
// rs.top + (ro.top - ro.top*s) - (t - t*s))
|
||||||
|
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
*/
|
||||||
|
setOrigin: function(a, b){
|
||||||
|
var ribbon_set = this.viewer.find('.ribbon-set')
|
||||||
|
|
||||||
|
if(typeof(a) == typeof(123) && typeof(b) == typeof(123)){
|
||||||
|
var t = a
|
||||||
|
var l = b
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if(a == null){
|
||||||
|
var img = this.getImage()
|
||||||
|
} else {
|
||||||
|
var img = this.getImage(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
var s = this.getScale()
|
||||||
|
var io = img.offset()
|
||||||
|
var vo = this.viewer.offset()
|
||||||
|
|
||||||
|
// get distance from center of image to top left corner of
|
||||||
|
// screen...
|
||||||
|
// NOTE: the result should be scale-neutral.
|
||||||
|
var l = (io.left - vo.left) + (img.width()*s)/2
|
||||||
|
var t = (io.top - vo.top) + (img.height()*s)/2
|
||||||
|
}
|
||||||
|
|
||||||
|
var rs = getElementOffset(ribbon_set)
|
||||||
|
|
||||||
|
var ot = t - rs.top
|
||||||
|
var ol = l - rs.left
|
||||||
|
|
||||||
|
console.log('### origin:', ol, ot)
|
||||||
|
|
||||||
|
shiftOriginTo(ribbon_set, ol, ot)
|
||||||
|
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1309,6 +1407,8 @@ module.RibbonsPrototype = {
|
|||||||
// implicitly (i.e. the default)
|
// implicitly (i.e. the default)
|
||||||
// NOTE: this will get absolute results relative to screen, view
|
// NOTE: this will get absolute results relative to screen, view
|
||||||
// scaling will have no effect...
|
// scaling will have no effect...
|
||||||
|
//
|
||||||
|
// XXX split this in two...(???)
|
||||||
_getOffset: function(target, vertical, horizontal, image_offset, scale){
|
_getOffset: function(target, vertical, horizontal, image_offset, scale){
|
||||||
vertical = vertical == null ? 'center' : vertical
|
vertical = vertical == null ? 'center' : vertical
|
||||||
horizontal = horizontal == null ? 'center' : horizontal
|
horizontal = horizontal == null ? 'center' : horizontal
|
||||||
@ -1333,8 +1433,12 @@ module.RibbonsPrototype = {
|
|||||||
var rl = ribbon.offset().left
|
var rl = ribbon.offset().left
|
||||||
var rst = ribbon_set.offset().top
|
var rst = ribbon_set.offset().top
|
||||||
|
|
||||||
var W = viewer.width()
|
// NOTE: not quite sure why need to multiply this by scale but
|
||||||
var H = viewer.height()
|
// without it this does not work with origin/translate but
|
||||||
|
// does fine with top/left offsets...
|
||||||
|
var W = viewer.width() * scale
|
||||||
|
var H = viewer.height() * scale
|
||||||
|
|
||||||
var w = image.width() * scale
|
var w = image.width() * scale
|
||||||
var h = image.height() * scale
|
var h = image.height() * scale
|
||||||
|
|
||||||
@ -1368,15 +1472,25 @@ module.RibbonsPrototype = {
|
|||||||
// center a ribbon vertically...
|
// center a ribbon vertically...
|
||||||
//
|
//
|
||||||
centerRibbon: function(target, offset, scale){
|
centerRibbon: function(target, offset, scale){
|
||||||
offset = offset == null
|
scale = scale == null ? this.getScale() : scale
|
||||||
? this._getOffset(target, null, null, null, scale)
|
// NOTE: when woring with origin we do not care about scale...
|
||||||
: offset
|
//scale = scale == null ? 1 : scale
|
||||||
|
|
||||||
// vertical offset...
|
offset = offset == null
|
||||||
this.viewer.find('.ribbon-set')
|
// XXX this should not get affected by scale or origin...
|
||||||
.css({
|
// XXX this gives correct resolts ONLY when we got scaled when
|
||||||
top: offset.top,
|
// focused on ribbon 0, in other cases it's messed up...
|
||||||
})
|
? this._getOffset(target, null, null, null, 1).top
|
||||||
|
: offset.top
|
||||||
|
|
||||||
|
var ot = this.getOrigin().top
|
||||||
|
// XXX something is still missing here...
|
||||||
|
// ...it's getting closer when enlarging and blows up when scale -> 0
|
||||||
|
offset -= (ot/scale - ot)
|
||||||
|
|
||||||
|
console.log('### offset-top:', offset)
|
||||||
|
|
||||||
|
setElementOffset(this.viewer.find('.ribbon-set'), 0, offset)
|
||||||
|
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
@ -1384,6 +1498,7 @@ module.RibbonsPrototype = {
|
|||||||
//
|
//
|
||||||
centerImage: function(target, mode, offset, scale){
|
centerImage: function(target, mode, offset, scale){
|
||||||
scale = scale == null ? this.getScale() : scale
|
scale = scale == null ? this.getScale() : scale
|
||||||
|
|
||||||
offset = offset == null
|
offset = offset == null
|
||||||
? this._getOffset(target, 'center', 'center', mode, scale)
|
? this._getOffset(target, 'center', 'center', mode, scale)
|
||||||
: offset
|
: offset
|
||||||
|
|||||||
@ -142,6 +142,10 @@ module.GLOBAL_KEYBOARD = {
|
|||||||
'#3': function(){ a.fitThree() },
|
'#3': function(){ a.fitThree() },
|
||||||
'#4': function(){ a.fitFour() },
|
'#4': function(){ a.fitFour() },
|
||||||
'#5': function(){ a.fitFive() },
|
'#5': function(){ a.fitFive() },
|
||||||
|
'#6': function(){ a.fitSix() },
|
||||||
|
'#7': function(){ a.fitSeven() },
|
||||||
|
'#8': function(){ a.fitEight() },
|
||||||
|
'#9': function(){ a.fitNine() },
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user