Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.google.gwt.query.client.plugins.effects.PropertiesAnimation Maven / Gradle / Ivy
/*
* Copyright 2011, The gwtquery team.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.query.client.plugins.effects;
import static com.google.gwt.query.client.GQuery.$;
import com.google.gwt.dom.client.Element;
import com.google.gwt.query.client.Function;
import com.google.gwt.query.client.GQuery;
import com.google.gwt.query.client.Properties;
import com.google.gwt.query.client.js.JsObjectArray;
import com.google.gwt.query.client.plugins.Effects;
import com.google.gwt.query.client.plugins.Effects.GQAnimation;
import com.google.gwt.query.client.plugins.effects.Fx.ColorFx;
import com.google.gwt.query.client.plugins.effects.Fx.ColorFx.BorderColorFx;
import com.google.gwt.regexp.shared.MatchResult;
import com.google.gwt.regexp.shared.RegExp;
/**
* Animation effects on any numeric CSS property.
*/
public class PropertiesAnimation extends GQAnimation {
/**
* Easing method to use.
*/
public static interface Easing {
public double interpolate(double progress);
/**
* @deprecated use EasingCurve.linear instead
*/
public Easing LINEAR = EasingCurve.linear;
/**
* @deprecated use EasingCurve.swing instead
*/
public Easing SWING = EasingCurve.swing;
}
/**
* This is a collection of most popular curves used in web animations
* implemented using the Bezier Curve instead of a different algorithm per
* animation.
*
* The toString() method returns the string parameter which can be used
* for CSS3 transition-timing-function properties, example:
*
transition-timing-function: ease;
transition-timing-function: cubic-bezier(0, 0, 1, 1);
*
*
* This enum can be used with customized transitions in this way:
*
$("#foo").animate($$("{top:'500px',left:'500px'}"), 400, EasingCurve.custom.with(.02,.01,.47,1));
*
*
*/
public static enum EasingCurve implements Easing {
linear (0, 0, 1, 1) {
public double interpolate(double p){return p;}
public String toString() {return "linear";}
},
ease (0.25, 0.1, 0.25, 1) {
public String toString() {return "ease";}
},
easeIn (0.42, 0, 1, 1) {
public String toString() {return "ease-in";}
},
easeOut (0, 0, 0.58, 1) {
public String toString() {return "ease-out";}
},
easeInOut (0.42, 0, 0.58, 1) {
public String toString() {return "ease-in-out";}
},
snap (0,1,.5,1),
swing (.02,.01,.47,1),
easeInCubic (.550,.055,.675,.190),
easeOutCubic (.215,.61,.355,1),
easeInOutCubic (.645,.045,.355,1),
easeInCirc (.6,.04,.98,.335),
easeOutCirc (.075,.82,.165,1),
easeInOutCirc (.785,.135,.15,.86),
easeInExpo (.95,.05,.795,.035),
easeOutExpo (.19,1,.22,1),
easeInOutExpo (1,0,0,1),
easeInQuad (.55,.085,.68,.53),
easeOutQuad (.25,.46,.45,.94),
easeInOutQuad (.455,.03,.515,.955),
easeInQuart (.895,.03,.685,.22),
easeOutQuart (.165,.84,.44,1),
easeInOutQuart (.77,0,.175,1),
easeInQuint (.755,.05,.855,.06),
easeOutQuint (.23,1,.32,1),
easeInOutQuint (.86,0,.07,1),
easeInSine (.47,0,.745,.715),
easeOutSine (.39,.575,.565,1),
easeInOutSine (.445,.05,.55,.95),
easeInBack (.6,-.28,.735,.045),
easeOutBack (.175, .885,.32,1.275),
easeInOutBack (.68,-.55,.265,1.55),
custom(0, 0, 1, 1);
private Bezier c = new Bezier(0, 0, 1, 1);
EasingCurve(double x1, double y1, double x2, double y2) {
with(x1, y1, x2, y2);
}
public Easing with(double x1, double y1, double x2, double y2) {
c = new Bezier(x1, y1, x2, y2);
return this;
}
public double interpolate(double progress) {
return c.f(progress);
}
public String toString() {
return "cubic-bezier(" + c + ")";
}
}
protected static final String[] ATTRS_TO_SAVE = new String[]{"overflow"};
private static final RegExp REGEX_NUMBER_UNIT = RegExp.compile("^([0-9+-.]+)(.*)?$");
protected static final RegExp REGEX_SYMBOL_NUMBER_UNIT = RegExp.compile("^([+-]=)?([0-9+-.]+)(.*)?$");
protected static final RegExp REGEX_NON_PIXEL_ATTRS =
RegExp.compile("z-?index|font-?weight|opacity|zoom|line-?height|scale|rotation|^\\$", "i");
private static final RegExp REGEX_COLOR_ATTR = RegExp.compile(".*color$", "i");
private static final RegExp REGEX_BORDERCOLOR = RegExp.compile("^bordercolor$", "i");
private static final RegExp REGEX_BACKGROUNDCOLOR =RegExp.compile("^backgroundcolor$", "i");
public static Fx computeFxProp(Element e, String key, String val,
boolean hidden) {
if (REGEX_COLOR_ATTR.test(key)) {
return computeFxColorProp(e, key, val);
}
return computeFxNumericProp(e, key, val, hidden);
}
private static Fx computeFxColorProp(Element e, String key, String val) {
if (REGEX_BORDERCOLOR.test(key)) {
return new BorderColorFx(e, val);
}
String initialColor = null;
if (REGEX_BACKGROUNDCOLOR.test(key)) {
// find the first parent having a background-color value (other than
// transparent)
Element current = e;
while ((initialColor == null || initialColor.length() == 0 || initialColor.equals("transparent"))
&& current != null) {
initialColor = GQuery.$(current).css(key, false);
current = !"body".equalsIgnoreCase(current.getTagName())
? current.getParentElement() : null;
}
if (initialColor == null || initialColor.length() == 0
|| initialColor.equals("transparent")) {
initialColor = "white";
}
} else {
initialColor = GQuery.$(e).css(key, true);
}
return new ColorFx(key, initialColor, val);
}
public static Fx computeFxNumericProp(Element e, String key, String val,
boolean hidden) {
GQuery g = Effects.$(e);
String unit = "";
if ("toggle".equals(val)) {
val = hidden ? "show" : "hide";
}
if (("show".equals(val) && !hidden) || ("hide").equals(val) && hidden) {
return null;
}
if (hidden) {
g.show();
}
// If key starts with $ we animate node attributes, otherwise css properties
double cur;
String rkey = null;
if (key.startsWith("$")) {
rkey = key.substring(1).toLowerCase();
String attr = g.attr(rkey);
MatchResult parts = REGEX_NUMBER_UNIT.exec(attr);
if (parts != null) {
String $1 = parts.getGroup(1);
String $2 = parts.getGroup(2);
cur = Double.parseDouble($1);
unit = $2 == null ? "" : $2;
} else {
cur = g.cur(key, true);
key = rkey;
}
} else {
cur = g.cur(key, true);
}
double start = cur, end = start;
if ("show".equals(val)) {
g.saveCssAttrs(key);
start = 0;
unit = REGEX_NON_PIXEL_ATTRS.test(key) ? "" : "px";
} else if ("hide".equals(val)) {
if (hidden) {
return null;
}
g.saveCssAttrs(key);
end = 0;
unit = REGEX_NON_PIXEL_ATTRS.test(key) ? "" : "px";
} else {
MatchResult parts = REGEX_SYMBOL_NUMBER_UNIT.exec(val);
if (parts != null) {
String $1 = parts.getGroup(1);
String $2 = parts.getGroup(2);
String $3 = parts.getGroup(3);
end = Double.parseDouble($2);
if (rkey == null) {
unit = REGEX_NON_PIXEL_ATTRS.test(key) ? "" : //
$3 == null || $3.isEmpty() ? "px" : $3;
if (!"px".equals(unit)) {
double to = end == 0 ? 1 : end;
g.css(key, to + unit);
start = to * start / g.cur(key, true);
g.css(key, start + unit);
}
} else if ($3 != null && !$3.isEmpty()) {
unit = $3;
}
if ($1 != null && !$1.isEmpty()) {
end = (("-=".equals($1) ? -1 : 1) * end) + start;
}
}
}
return new Fx(key, val, start, end, unit, rkey);
}
protected Easing easing;
protected JsObjectArray effects;
private Function[] funcs;
private Effects g;
public PropertiesAnimation(Element elem, Properties p, Function... funcs) {
this(null, elem, p, funcs);
}
public PropertiesAnimation(Easing ease, Element elem, Properties p, Function... funcs) {
try {
easing = EasingCurve.valueOf(p.getStr("easing"));
} catch (Exception e) {
}
if (easing == null) {
easing = ease;
}
if (easing == null) {
easing = EasingCurve.swing;
}
this.funcs = funcs;
setProperties(p);
setElement(elem);
g = $(e).as(Effects.Effects);
}
@Override
public void onCancel() {
Boolean jumpToEnd = Effects.$(e).data(Effects.JUMP_TO_END, Boolean.class);
if (jumpToEnd != null && jumpToEnd){
onComplete();
} else {
g.dequeue();
g.restoreCssAttrs(ATTRS_TO_SAVE);
}
}
@Override
public void onComplete() {
super.onComplete();
for (int i = 0; i < effects.length(); i++) {
Fx fx = effects.get(i);
if ("hide".equals(fx.value)) {
g.hide();
g.restoreCssAttrs(fx.cssprop);
} else if ("show".equals(fx.value)) {
g.show();
g.restoreCssAttrs(fx.cssprop);
}
}
g.restoreCssAttrs(ATTRS_TO_SAVE);
g.each(funcs);
g.dequeue();
}
@Override
public void onStart() {
effects = JsObjectArray.create();
boolean resize = false;
boolean move = false;
boolean hidden = !g.isVisible();
Fx fx;
// g.show();
for (String key : prps.keys()) {
String val = prps.getStr(key);
if ((fx = computeFxProp(e, key, val, hidden)) != null) {
effects.add(fx);
resize = resize || "height".equals(key) || "width".equals(key);
move = move || "top".equals(key) || "left".equals(key);
}
}
g.saveCssAttrs(ATTRS_TO_SAVE);
if (resize) {
g.css("overflow", "hidden");
}
if (move && !g.css("position", true).matches("absolute|relative|fixed")) {
g.css("position", "relative");
}
super.onStart();
}
@Override
public void onUpdate(double progress) {
for (int i = 0; i < effects.length(); i++) {
effects.get(i).applyValue(g, progress);
}
}
@Override
protected double interpolate(double progress) {
return easing.interpolate(progress);
}
}