mirror of
https://github.com/blasten/turn.js.git
synced 2026-07-13 21:31:10 +08:00
extraction du calcul du pli dans une fonction interne pure
This commit is contained in:
parent
a5bf642e07
commit
688034f7d3
@ -78,6 +78,82 @@ describe('turn.js jQuery plugin', () => {
|
||||
expect($.fn.transform).toBeTypeOf('function');
|
||||
});
|
||||
|
||||
it('calculates fold geometry without DOM for every corner', () => {
|
||||
fixture.window.close();
|
||||
fixture = createFixture(4, {
|
||||
__TURNJS_TEST_HOOKS__: {}
|
||||
});
|
||||
|
||||
const calculateFoldGeometry = fixture.window.__TURNJS_TEST_HOOKS__.calculateFoldGeometry;
|
||||
const base = {
|
||||
width: 300,
|
||||
height: 400,
|
||||
wrapperHeight: 500,
|
||||
frontGradient: true,
|
||||
backGradient: true
|
||||
};
|
||||
const cases = [
|
||||
{
|
||||
point: { corner: 'tl', x: 90, y: 120 },
|
||||
origin: { x: 0, y: 0 },
|
||||
endingPoint: { x: 600, y: 0 },
|
||||
top: true,
|
||||
left: true
|
||||
},
|
||||
{
|
||||
point: { corner: 'tr', x: 210, y: 120 },
|
||||
origin: { x: 300, y: 0 },
|
||||
endingPoint: { x: -300, y: 0 },
|
||||
top: true,
|
||||
left: false
|
||||
},
|
||||
{
|
||||
point: { corner: 'bl', x: 90, y: 280 },
|
||||
origin: { x: 0, y: 400 },
|
||||
endingPoint: { x: 600, y: 400 },
|
||||
top: false,
|
||||
left: true
|
||||
},
|
||||
{
|
||||
point: { corner: 'br', x: 210, y: 280 },
|
||||
origin: { x: 300, y: 400 },
|
||||
endingPoint: { x: -300, y: 400 },
|
||||
top: false,
|
||||
left: false
|
||||
}
|
||||
];
|
||||
|
||||
expect(calculateFoldGeometry).toBeTypeOf('function');
|
||||
|
||||
for (const item of cases) {
|
||||
const originalPoint = { ...item.point };
|
||||
const geometry = calculateFoldGeometry({ ...base, ...item });
|
||||
|
||||
expect(item.point).toEqual(originalPoint);
|
||||
expect(geometry.point.corner).toBe(item.point.corner);
|
||||
expect(geometry.top).toBe(item.top);
|
||||
expect(geometry.left).toBe(item.left);
|
||||
expect(Number.isFinite(geometry.alpha)).toBe(true);
|
||||
expect(Number.isFinite(geometry.angle)).toBe(true);
|
||||
expect(Number.isFinite(geometry.px)).toBe(true);
|
||||
expect(Number.isFinite(geometry.tr.x)).toBe(true);
|
||||
expect(Number.isFinite(geometry.tr.y)).toBe(true);
|
||||
expect(Number.isFinite(geometry.move.x)).toBe(true);
|
||||
expect(Number.isFinite(geometry.move.y)).toBe(true);
|
||||
expect(Number.isFinite(geometry.df.x)).toBe(true);
|
||||
expect(Number.isFinite(geometry.df.y)).toBe(true);
|
||||
expect(Number.isFinite(geometry.gradient.opacity)).toBe(true);
|
||||
expect(Number.isFinite(geometry.gradient.size)).toBe(true);
|
||||
expect(geometry.gradient.endPointA).toBeDefined();
|
||||
expect(geometry.gradient.endPointB).toBeDefined();
|
||||
|
||||
if (item.left)
|
||||
expect(geometry.point.x).toBeGreaterThanOrEqual(1);
|
||||
else
|
||||
expect(geometry.point.x).toBeLessThanOrEqual(base.width - 1);
|
||||
}
|
||||
});
|
||||
|
||||
it('initializes a book and exposes page, view, pages and size state', () => {
|
||||
const { $ } = fixture;
|
||||
const $book = $('#book');
|
||||
|
||||
240
turn.js
240
turn.js
@ -218,6 +218,127 @@ var has3d,
|
||||
return vendor;
|
||||
},
|
||||
|
||||
// Calculates the fold geometry without touching the DOM
|
||||
|
||||
calculateFoldGeometry = function(opts) {
|
||||
|
||||
var alpha = 0,
|
||||
angle = 0,
|
||||
px,
|
||||
gradientEndPointA,
|
||||
gradientEndPointB,
|
||||
gradientStartV,
|
||||
gradientSize,
|
||||
gradientOpacity,
|
||||
mv = point2D(0, 0),
|
||||
df = point2D(0, 0),
|
||||
tr = point2D(0, 0),
|
||||
width = opts.width,
|
||||
height = opts.height,
|
||||
h = opts.wrapperHeight,
|
||||
o = opts.origin,
|
||||
point = point2D(opts.point.x, opts.point.y),
|
||||
top = opts.point.corner.substr(0, 1) == 't',
|
||||
left = opts.point.corner.substr(1, 1) == 'l';
|
||||
|
||||
point.corner = opts.point.corner;
|
||||
|
||||
if (left)
|
||||
point.x = Math.max(point.x, 1);
|
||||
else
|
||||
point.x = Math.min(point.x, width-1);
|
||||
|
||||
var compute = function() {
|
||||
var rel = point2D((o.x) ? o.x - point.x : point.x, (o.y) ? o.y - point.y : point.y),
|
||||
tan = (Math.atan2(rel.y, rel.x)),
|
||||
middle;
|
||||
|
||||
alpha = A90 - tan;
|
||||
angle = deg(alpha);
|
||||
middle = point2D((left) ? width - rel.x/2 : point.x + rel.x/2, rel.y/2);
|
||||
|
||||
var gamma = alpha - Math.atan2(middle.y, middle.x),
|
||||
distance = Math.max(0, Math.sin(gamma) * Math.sqrt(Math.pow(middle.x, 2) + Math.pow(middle.y, 2)));
|
||||
|
||||
tr = point2D(distance * Math.sin(alpha), distance * Math.cos(alpha));
|
||||
|
||||
if (alpha > A90) {
|
||||
|
||||
tr.x = tr.x + Math.abs(tr.y * Math.tan(tan));
|
||||
tr.y = 0;
|
||||
|
||||
if (Math.round(tr.x*Math.tan(PI-alpha)) < height) {
|
||||
|
||||
point.y = Math.sqrt(Math.pow(height, 2)+2 * middle.x * rel.x);
|
||||
if (top) point.y = height - point.y;
|
||||
return compute();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (alpha>A90) {
|
||||
var beta = PI-alpha, dd = h - height/Math.sin(beta);
|
||||
mv = point2D(Math.round(dd*Math.cos(beta)), Math.round(dd*Math.sin(beta)));
|
||||
if (left) mv.x = - mv.x;
|
||||
if (top) mv.y = - mv.y;
|
||||
}
|
||||
|
||||
px = Math.round(tr.y/Math.tan(alpha) + tr.x);
|
||||
|
||||
var side = width - px,
|
||||
sideX = side*Math.cos(alpha*2),
|
||||
sideY = side*Math.sin(alpha*2);
|
||||
df = point2D(Math.round( (left ? side -sideX : px+sideX)), Math.round((top) ? sideY : height - sideY));
|
||||
|
||||
gradientSize = side*Math.sin(alpha);
|
||||
var far = Math.sqrt(Math.pow(opts.endingPoint.x-point.x, 2)+Math.pow(opts.endingPoint.y-point.y, 2));
|
||||
|
||||
gradientOpacity = (far<width) ? far/width : 1;
|
||||
|
||||
if (opts.frontGradient) {
|
||||
|
||||
gradientStartV = gradientSize>100 ? (gradientSize-100)/gradientSize : 0;
|
||||
gradientEndPointA = point2D(gradientSize*Math.sin(A90-alpha)/height*100, gradientSize*Math.cos(A90-alpha)/width*100);
|
||||
|
||||
if (top) gradientEndPointA.y = 100-gradientEndPointA.y;
|
||||
if (left) gradientEndPointA.x = 100-gradientEndPointA.x;
|
||||
}
|
||||
|
||||
if (opts.backGradient) {
|
||||
|
||||
gradientEndPointB = point2D(gradientSize*Math.sin(alpha)/width*100, gradientSize*Math.cos(alpha)/height*100);
|
||||
if (!left) gradientEndPointB.x = 100-gradientEndPointB.x;
|
||||
if (!top) gradientEndPointB.y = 100-gradientEndPointB.y;
|
||||
}
|
||||
|
||||
tr.x = Math.round(tr.x);
|
||||
tr.y = Math.round(tr.y);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
compute();
|
||||
|
||||
return {
|
||||
point: point,
|
||||
alpha: alpha,
|
||||
angle: angle,
|
||||
tr: tr,
|
||||
move: mv,
|
||||
df: df,
|
||||
px: px,
|
||||
top: top,
|
||||
left: left,
|
||||
gradient: {
|
||||
endPointA: gradientEndPointA,
|
||||
endPointB: gradientEndPointB,
|
||||
startV: gradientStartV,
|
||||
size: gradientSize,
|
||||
opacity: gradientOpacity
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
// Adds gradients
|
||||
|
||||
gradient = function(obj, p0, p1, colors, numColors) {
|
||||
@ -1593,12 +1714,9 @@ flipMethods = {
|
||||
var that = this,
|
||||
a = 0,
|
||||
alpha = 0,
|
||||
beta,
|
||||
px,
|
||||
gradientEndPointA,
|
||||
gradientEndPointB,
|
||||
gradientStartV,
|
||||
gradientSize,
|
||||
gradientOpacity,
|
||||
mv = point2D(0, 0),
|
||||
df = point2D(0, 0),
|
||||
@ -1606,89 +1724,24 @@ flipMethods = {
|
||||
width = this.width(),
|
||||
height = this.height(),
|
||||
folding = flipMethods._foldingPage.call(this),
|
||||
tan = Math.tan(alpha),
|
||||
data = this.data().f,
|
||||
ac = data.opts.acceleration,
|
||||
h = data.wrapper.height(),
|
||||
o = flipMethods._c.call(this, point.corner),
|
||||
backGradient = flipMethods._backGradient.call(this),
|
||||
geometry = calculateFoldGeometry({
|
||||
point: point,
|
||||
width: width,
|
||||
height: height,
|
||||
wrapperHeight: h,
|
||||
origin: o,
|
||||
endingPoint: flipMethods._c2.call(this, point.corner),
|
||||
frontGradient: data.opts.frontGradient,
|
||||
backGradient: backGradient
|
||||
}),
|
||||
top = point.corner.substr(0, 1) == 't',
|
||||
left = point.corner.substr(1, 1) == 'l',
|
||||
|
||||
compute = function() {
|
||||
var rel = point2D((o.x) ? o.x - point.x : point.x, (o.y) ? o.y - point.y : point.y),
|
||||
tan = (Math.atan2(rel.y, rel.x)),
|
||||
middle;
|
||||
|
||||
alpha = A90 - tan;
|
||||
a = deg(alpha);
|
||||
middle = point2D((left) ? width - rel.x/2 : point.x + rel.x/2, rel.y/2);
|
||||
|
||||
var gamma = alpha - Math.atan2(middle.y, middle.x),
|
||||
distance = Math.max(0, Math.sin(gamma) * Math.sqrt(Math.pow(middle.x, 2) + Math.pow(middle.y, 2)));
|
||||
|
||||
tr = point2D(distance * Math.sin(alpha), distance * Math.cos(alpha));
|
||||
|
||||
if (alpha > A90) {
|
||||
|
||||
tr.x = tr.x + Math.abs(tr.y * Math.tan(tan));
|
||||
tr.y = 0;
|
||||
|
||||
if (Math.round(tr.x*Math.tan(PI-alpha)) < height) {
|
||||
|
||||
point.y = Math.sqrt(Math.pow(height, 2)+2 * middle.x * rel.x);
|
||||
if (top) point.y = height - point.y;
|
||||
return compute();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (alpha>A90) {
|
||||
var beta = PI-alpha, dd = h - height/Math.sin(beta);
|
||||
mv = point2D(Math.round(dd*Math.cos(beta)), Math.round(dd*Math.sin(beta)));
|
||||
if (left) mv.x = - mv.x;
|
||||
if (top) mv.y = - mv.y;
|
||||
}
|
||||
|
||||
px = Math.round(tr.y/Math.tan(alpha) + tr.x);
|
||||
|
||||
var side = width - px,
|
||||
sideX = side*Math.cos(alpha*2),
|
||||
sideY = side*Math.sin(alpha*2);
|
||||
df = point2D(Math.round( (left ? side -sideX : px+sideX)), Math.round((top) ? sideY : height - sideY));
|
||||
|
||||
|
||||
// GRADIENTS
|
||||
|
||||
gradientSize = side*Math.sin(alpha);
|
||||
var endingPoint = flipMethods._c2.call(that, point.corner),
|
||||
far = Math.sqrt(Math.pow(endingPoint.x-point.x, 2)+Math.pow(endingPoint.y-point.y, 2));
|
||||
|
||||
gradientOpacity = (far<width) ? far/width : 1;
|
||||
|
||||
|
||||
if (data.opts.frontGradient) {
|
||||
|
||||
gradientStartV = gradientSize>100 ? (gradientSize-100)/gradientSize : 0;
|
||||
gradientEndPointA = point2D(gradientSize*Math.sin(A90-alpha)/height*100, gradientSize*Math.cos(A90-alpha)/width*100);
|
||||
|
||||
if (top) gradientEndPointA.y = 100-gradientEndPointA.y;
|
||||
if (left) gradientEndPointA.x = 100-gradientEndPointA.x;
|
||||
}
|
||||
|
||||
if (flipMethods._backGradient.call(that)) {
|
||||
|
||||
gradientEndPointB = point2D(gradientSize*Math.sin(alpha)/width*100, gradientSize*Math.cos(alpha)/height*100);
|
||||
if (!left) gradientEndPointB.x = 100-gradientEndPointB.x;
|
||||
if (!top) gradientEndPointB.y = 100-gradientEndPointB.y;
|
||||
}
|
||||
//
|
||||
|
||||
tr.x = Math.round(tr.x);
|
||||
tr.y = Math.round(tr.y);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
transform = function(tr, c, x, a) {
|
||||
|
||||
var f = ['0', 'auto'], mvW = (width-h)*x[0]/100, mvH = (height-h)*x[1]/100,
|
||||
@ -1715,7 +1768,7 @@ flipMethods = {
|
||||
3,
|
||||
alpha);
|
||||
|
||||
if (flipMethods._backGradient.call(that))
|
||||
if (backGradient)
|
||||
gradient(data.bshadow,
|
||||
point2D(left?0:100, top?0:100),
|
||||
point2D(gradientEndPointB.x, gradientEndPointB.y),
|
||||
@ -1723,34 +1776,40 @@ flipMethods = {
|
||||
[0.9, 'rgba(0,0,0,'+(0.18*gradientOpacity)+')'],
|
||||
[1, 'rgba(0,0,0,0)']],
|
||||
3);
|
||||
|
||||
|
||||
};
|
||||
|
||||
point.x = geometry.point.x;
|
||||
point.y = geometry.point.y;
|
||||
alpha = geometry.alpha;
|
||||
a = geometry.angle;
|
||||
tr = geometry.tr;
|
||||
mv = geometry.move;
|
||||
df = geometry.df;
|
||||
top = geometry.top;
|
||||
left = geometry.left;
|
||||
gradientEndPointA = geometry.gradient.endPointA;
|
||||
gradientEndPointB = geometry.gradient.endPointB;
|
||||
gradientStartV = geometry.gradient.startV;
|
||||
gradientOpacity = geometry.gradient.opacity;
|
||||
|
||||
switch (point.corner) {
|
||||
case 'tl' :
|
||||
point.x = Math.max(point.x, 1);
|
||||
compute();
|
||||
transform(tr, [1,0,0,1], [100, 0], a);
|
||||
data.fpage.transform(translate(-height, -width, ac) + rotate(90-a*2) , '100% 100%');
|
||||
folding.transform(rotate(90) + translate(0, -height, ac), '0% 0%');
|
||||
break;
|
||||
case 'tr' :
|
||||
point.x = Math.min(point.x, width-1);
|
||||
compute();
|
||||
transform(point2D(-tr.x, tr.y), [0,0,0,1], [0, 0], -a);
|
||||
data.fpage.transform(translate(0, -width, ac) + rotate(-90+a*2) , '0% 100%');
|
||||
folding.transform(rotate(270) + translate(-width, 0, ac), '0% 0%');
|
||||
break;
|
||||
case 'bl' :
|
||||
point.x = Math.max(point.x, 1);
|
||||
compute();
|
||||
transform(point2D(tr.x, -tr.y), [1,1,0,0], [100, 100], -a);
|
||||
data.fpage.transform(translate(-height, 0, ac) + rotate(-90+a*2), '100% 0%');
|
||||
folding.transform(rotate(270) + translate(-width, 0, ac), '0% 0%');
|
||||
break;
|
||||
case 'br' :
|
||||
point.x = Math.min(point.x, width-1);
|
||||
compute();
|
||||
transform(point2D(-tr.x, -tr.y), [0,1,1,0], [0, 100], a);
|
||||
data.fpage.transform(rotate(90-a*2), '0% 0%');
|
||||
folding.transform(rotate(90) + translate(0, -height, ac), '0% 0%');
|
||||
@ -2104,6 +2163,9 @@ $.extend($.fn, {
|
||||
});
|
||||
|
||||
|
||||
if (window.__TURNJS_TEST_HOOKS__)
|
||||
window.__TURNJS_TEST_HOOKS__.calculateFoldGeometry = calculateFoldGeometry;
|
||||
|
||||
$.isTouch = isTouch;
|
||||
|
||||
})(jQuery);
|
||||
|
||||
2
turn.min.js
vendored
2
turn.min.js
vendored
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user