// ZIM - Interactive Media framework at https://zimjs.com - code creativity!
// Also see https://zimjs.com/distill to minify only the functions in your app
// (c) 2020 Dan Zen - free to use - donations welcome of course! https://zimjs.com/donate
// global variable to hold default frame - used by other ZIM modules like physics, etc.
var zimDefaultFrame;
//////////////// ZIM WRAP //////////////
// Zim Wrap creates global wrapper functions for less typing
// set var zon=false before calling zim scripts to hide script comments
if (typeof zon == "undefined") var zon = true; // comments from zim scripts
if (typeof zns == 'undefined') var zns = false; // require zim namespace
/*--
zog(item1, item2, etc.) ~ log
zog
global function
DESCRIPTION
Short version of console.log()
to log the item(s) to the console.
Use F12 to open your Browser console.
zog is dedicated to Pragma (Madeline Zen) who was coding with Dr Abstract (Dan Zen) from the start
Also comes in six ZIM colors:
zogg("green");
zogp("pink");
zogb("blue");
zogr("red");
zogy("yellow");
zogo("orange");
Note: If zon (comments on) is set to false before ZIM runs, then all zog() commands are turned off
EXAMPLE
zog("hello", circle.x); // logs these values to the console
END EXAMPLE
PARAMETERS
item1, item2 (optional), etc. - items (expressions) to log to the console
RETURNS items it is logging separated by a space if more than one
--*///+0
// reported a bug in Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=1280818
// that after FF 46 binding the console did not show file and line number
// this is fixed in FF 50 - quite the conversation this stirred
var zog = zon?console.log.bind(console):function(){};
// Thanks Ami and Yalon for the technique
var zogStyle = " border:thin solid black; color: black";
var zogg = zon?console.log.bind(console, "%c Z ", "background: #acd241;"+zogStyle):function(){};
var zogp = zon?console.log.bind(console, "%c Z ", "background: #e472c4;"+zogStyle):function(){};
var zogb = zon?console.log.bind(console, "%c Z ", "background: #50c4b7;"+zogStyle):function(){};
var zogr = zon?console.log.bind(console, "%c Z ", "background: #fb4758;"+zogStyle):function(){};
var zogy = zon?console.log.bind(console, "%c Z ", "background: #ebcb35;"+zogStyle):function(){};
var zogo = zon?console.log.bind(console, "%c Z ", "background: #f58e25;"+zogStyle):function(){};
var zogl = zon?console.log.bind(console, "%c Z ", "background: #eeeeee;"+zogStyle):function(){};
var zogd = zon?console.log.bind(console, "%c Z ", "background: #444444; border:thin solid black; color: white"):function(){};
//-0
/*--
zid(string) ~ id
zid
global function
DESCRIPTION
Short version of document.getElementById(string)
to access an HTML tag by its id.
EXAMPLE
zid("logo").addEventListener("click", function(){});
END EXAMPLE
PARAMETERS
string - the id of the tag you are wanting to access
RETURNS HTML tag with id of string or null if not found
--*///+1
function zid(s) {
z_d("1");
return document.getElementById(s);
} //-1
/*--
zss(string) ~ css
zss
global function
DESCRIPTION
Short version of document.getElementById(string).style
to access the style property of an HTML tag by the tag id.
EXAMPLE
zss("logo").margin = "10px";
END EXAMPLE
PARAMETERS
string - the id of the tag whose style you are wanting to access
RETURNS style property of HTML tag with id of string or undefined if not found
--*///+2
function zss(s) {
z_d("2");
if (document.getElementById(s)) {return document.getElementById(s).style;}
else if (zon) zogy("zss(): id not found");
} //-2
/*--
zgo(url, target, width, height, fullscreen, modal) ~ go
zgo
global function
DESCRIPTION
Short version of either window.location.href or window.open
to open a link in the same window or a specified window.
EXAMPLE
zid("logo").addEventListener("click", function(){zgo("https://zimjs.com");});
// with a ZIM object:
var button = new Button();
button.center(stage);
button.on("click", function() {zgo("http://zimjs.com");});
END EXAMPLE
PARAMETERS
url - the link to use (Absolute, Relative or Virtual)
target - (default null) the string name of a window (tab) _blank for new window each time
width - (default null) width of window (use with fullscreen true)
height - (default null) height of window (use with fullscreen true)
fullscreen - (default null) not really full screen but rather opens in a new window not tab
modal - (default false) set to true to force user to close window
RETURNS null if opening in same window or reference to the window otherwise
--*///+3
function zgo(u,t,w,h,f,m) {
z_d("3");
if ((zot(t) && t != "") || t == "_self") {
window.location.href = u;
} else {
var added = "";
if (w) added += "width=" + w + ",";
if (h) added += "height=" + h + ",";
if (f) added += "fullscreen=yes,";
if (m) added += "modal=yes,alwaysRaised=yes";
return window.open(u,t,added);
}
} //-3
/*--
zum(string) ~ num
zum
global function
DESCRIPTION
Takes the units off a string number.
Converts "10px" string from styles to number 10, for instance.
If there is no value then this will return 0.
EXAMPLE
// in HTML
LOGO
// in JavaScript
var left = zum(zss("logo").left); // converts 10px to the Number 10
left += 20; // adds 20 to 10
zss("logo").left = left + "px"; // assigns 30px to left style
END EXAMPLE
PARAMETERS
string - the string representation of a number eg. "10px"
RETURNS a Number
--*///+4
function zum(s) {
z_d("4");
if (zot(s)) return;
return Number(String(s).replace(/[^\d\.\-]/g, ''));
} //-4
/*--
zot(value) ~ not
zot
global function
DESCRIPTION
Test to see if value has no value (value must exist as var or parameter)
or if value has been set to null.
Good for setting function defaults.
Really just asking if the value == null.
Often we forget exactly how to do this - it is tricky:
value === null, value == undefined, value == 0, !value DO NOT WORK.
EXAMPLE
if (zot(width)) width = 100;
// equivalent to
if (width == null) width = 100;
END EXAMPLE
PARAMETERS
value - a variable or parameter you want to see if there is no value assigned
RETURNS Boolean true if value does not exist
--*///+4.5
function zot(v) {
return v==null; // both null and undefined match but not false or 0
}//-4.5
/*--
zop(e) ~ stop
zop
global function
DESCRIPTION
Stop event propagation to subsequently added existing listeners.
Must pass it e || window.event from your event function.
NOTE: this is not canceling the default action -
to cancel default action use e.preventDefault();
EXAMPLE
zid("button").addEventListener("click", function(e) {
// do something
zop(e||window.event);
});
END EXAMPLE
PARAMETERS
e - the event object from your event function
collect the event object as e and then pass in e || window.event
RETURNS null
--*///+5
function zop(e) {
z_d("5");
if (zot(e)) return;
if (e.stopImmediatePropagation) e.stopImmediatePropagation();
if (window.event) window.event.cancelBubble=true;
} //-5
/*--
zil() ~ still
zil
global function
DESCRIPTION
Stop keys from moving content - arrows, spacebar, pgup, pgdown, home, end.
Stop scroll wheel from moving content - scrolling the canvas for instance.
ZIM Frame does this in the full, fit and outside scale modes.
If not using Frame, then you can do this once at the start of your code.
Returns an array of references to three listeners: [keydown, wheel and DOMMouseScroll].
Use these to removeEventListeners.
The arrows, etc, still work but just not their default window behaviour.
EXAMPLE
// at the top of your code
var listenersArray = zil();
// key and mousewheel arrows, spacebar, etc.
// will have their default actions stopped until you remove the listeners:
// window.removeEventListener("keydown", listenersArray[0]); // etc.
END EXAMPLE
RETURNS an Array
--*///+6
function zil() {
z_d("6");
var a = function(e) {if (!e) e = event; if (e.keyCode && (e.keyCode >= 32 && e.keyCode <= 40)) e.preventDefault();}
var b = function(e) {if (!e) e = event; e.preventDefault();}
var c = b;
window.addEventListener("keydown", a, {passive:false});
window.addEventListener("wheel", b, {passive:false});
window.addEventListener("DOMMouseScroll", c, {passive:false});
return [a, b, c];
} //-6
/*--
zet(selector) ~ set
zet
global function
DESCRIPTION
Uses document.querySelectorAll() to get a list of tags.
Returns a ZIM Zet object which can be used to add events or styles to the set.
EXAMPLE
zet(".class").on("click", function(){}); // would add function event to all tags with the class
zet("p").css("color", "goldenrod"); // would make the text of all paragraphs goldenrod
zet("#test").css({color:"red", "backgound-color":"blue", paddingLeft:"20px"});
// set a custom open property on all section bars to false
zet("section .bar").prop("open", false);
// set the custom open property on all section bars to true and set the innerHTML to CLOSE
zet("section .bar").prop({open: true, innerHTML: "CLOSE"});
END EXAMPLE
PARAMETERS
selector - a CSS query selector such as a class, id, tag, or multiple selectors separated by commands
can also be complex selectors suchs as ".class img"
METHODS (on the returned Zet object)
zet(selector).on(type, function) - a shortcut for addEventListener() and will be added to all tags matching the selector
zet(selector).off(type, function) - a shortcut for removeEventListener() and will be remove from all tags matching the selector
zet(selector).css(property, value) - gets and sets styles
- gets the first programmatic property if a single string property is passed
- sets the property to the value on each of the Zet's tags from the selector passed to zet()
- if an object of properties and values is passed as the single parameter then sets all these properties
- NOTE: style names do not need quotes unless the dash is used - so camelCase does not require quotes
- NOTE: remember that commas are used for objects - not the semi-colon as in CSS
zet(selector).prop(property, value) - gets or sets a property on a set of tags
- if an object of properties and values is provided as a single parameter, then sets all these on the set
- else if no value is set then returns an array of the set tags values for the property
- else if value is a single value then sets the property of the tags in the set to the value
PROPERTIES (on the returned Zet object)
tags - an HTML NodeList tag list
RETURNS Zet object with on(), off(), css() methods and tags property (NodeList tag list)
--*///+6.1
function zet(selector) {
z_d("6.1");
function Zet() {
var that = this;
this.on = function(type, call) {
if (zot(selector) || zot(type) || zot(call)) return;
var tags = that.tags;
for (var i=0; ib or a.5) {a*=-1; b*=-1;};
if (integer) if (a>b) {a++;} else if (b>a) {b++;}
var r;
if (a == 0 && b == 0) return 0;
else if (b == 0) r = Math.random()*a;
else r = Math.min(a,b) + Math.random()*(Math.max(a,b)-Math.min(a,b));
if (integer) return Math.floor(r);
else return r;
}//-9
/*--
zim.series = function(array|item1, item2, item3)
series
zim function
DESCRIPTION
Returns a function that will return each value passed as a parameter (or an Array) in order
This goes in sequence each time the function is called
Use this to pass a series in to any ZIM VEE value so a looping series is obtained
As of ZIM 10.9.0 series has step, jump, bounce, reverse and constrain settings
NOTE: was called makeSeries() which is now depricated (makeSeries does not have 10.9.0 settings)
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// note - do not call the variable name series
var colors = series(red, green, blue);
colors(); // red
colors(); // green
colors(); // blue
colors(); // red, etc.
// or
var colors = [red, green, blue];
var s = series(colors);
s(); // red
s(); // green
s(); // blue
s(); // red, etc.
new Tile(new Rectangle(10,10,[blue, red]), 10, 10); would randomize colors
new Tile(new Rectangle(10,10,series(blue, red)), 10, 10); would alternate colors
END EXAMPLE
EXAMPLE
STYLE = {color:series(pink, green, blue)}
loop(9, function (i) {
new Circle(100).loc(110+i*100, 400)
});
END EXAMPLE
EXAMPLE
// added functionality as of ZIM 10.9.0
// start at index 3, reverse and don't go past 0
var nums = series(0, 1, 2, 3, 4).jump(3).reverse().constrain();
loop(5, function(){
zogb(nums()); // 3,2,1,0,0 (blue in console)
});
nums.reverse(false); // go forward - note, still starting at index 0
zogg(nums()); // 0 (green in console)
zogg(nums()); // 1
zogg(nums()); // 2
nums.bounce(); // go back and forth rather than default loop
loop(5, function(){
zogy(nums()); // 3,4,3,2,1 (yellow in console)
});
nums.step(3); // sitting at 0 then increase the step to 3
loop(5, function(){
zogr(nums()); // 0,3,2,1,4 (red in console)
// 3->6 bounces off 4 with two back to 2
// 2->-1 bounces off 0 with one forward to 1
// tricky but correct
});
zogp(nums.index); // 1 - coming back 3 steps from 4 to 1 as current index
END EXAMPLE
PARAMETERS
array|item1 - the first item - or an array of results that will be called in order as the resulting function is called
// when used with ZIM VEE - the values may be further ZIM VEE values (including more series values)
item2 - the second item if the first is not an array
item3 - the third item, etc. to as many items as needed
METHODS
step(num) - num defaults to 1 - the number of items to move the index - or use index property
jump(index) - jump to an index but do not run it - the next call to the series will run here
reverse(boolean) - boolean defaults to true - reverses direction - or pass in false to cancel reverse
bounce(boolean) - boolean defaults to true - back and forth between 0 and length-1 - or pass in false to cancel bounce
constrain(boolean) - boolean defaults to true - keeps index between 0 and length-1 - or pass in false to cancel constrain
PROPERTIES
array - an array of items passed in to the function
length - the length of the series
index - get or set the current index of the series - what will run next
RETURNS a function that can be called many times - each time returning the next value in the series
--*///+13.61
zim.series = function() {
z_d("13.61");
var array;
if (arguments.length == 0) return function(){};
if (arguments.length == 1 && Array.isArray(arguments[0])) array = arguments[0];
else array = arguments;
var count = 0;
var dir = 1;
var step = 1;
var bounce = false;
var constrain = false;
var f = function() {
var val = array[(array.length*10+count)%array.length];
if (bounce) {
if (dir > 0 && count+dir*step >= array.length) {
dir = -1;
count = (array.length-1)-(count+step-(array.length-1));
} else if (dir < 0 && count+dir*step < 0) {
dir = 1;
count = step - count;
} else {
count += dir*step;
}
} else if (constrain) {
if (dir > 0 && count+dir*step >= array.length) count = array.length-1;
else if (dir < 0 && count+dir*step < 0) count = 0;
else count += dir*step;
} else {
count += dir*step;
}
return val;
}
f.array = array;
f.type = "series";
Object.defineProperty(f, 'index', {
get: function() {
return (array.length*10+count)%array.length;
},
set: function(value) {
count = value;
}
});
f.jump = function(value) {
count = value;
return f;
}
f.reverse = function(value) {
if (zot(value)) value = true;
if (value) dir = -1;
else dir = 1;
return f;
}
f.bounce = function(value) {
// normalize count
if (zot(value)) value = true;
count = (array.length*10+count)%array.length;
bounce = value;
return f;
}
f.step = function(value) {
if (zot(value)) value = 1;
step = Math.floor(value);
return f;
}
f.constrain = function(value) {
if (zot(value)) value = true;
constrain = value;
return f;
}
return f;
}//-13.61
/*--
zim.makeSeries = function(array)
depreciated - use series()
--*///+13.6
zim.makeSeries = function(array) {
z_d("13.6");
if (zot(array)) return function(){};
var count = 0;
var f = function() {
return array[(count++)%array.length];
}
f.array = array;
return f;
}//-13.6
/*--
zim.loop = function(obj, call, reverse, step, start, end)
loop
zim function
DESCRIPTION
1. If you pass in a Number for obj then loop() does function call that many times
and passes function call the currentIndex, totalLoops, startIndex, endIndex, obj.
By default, the index starts at 0 and counts up to one less than the number.
So this is like: for (var i=0; i6) return "break"; // quit loop when > 6
zog(i);
});
loop(10, function(i), {
zog(i); // 9-0 in console
}, true);
loop(10, function (i) {
zog(i); // 5-9
}, null, 1, 5)
// the start parameter cannot be less than 0
// to get negative values for i subtract a desired value inside the loop
var colors = [green, yellow, pink];
loop(colors, function(color, index, start, end, array) { // do not have to collect all these
zog(color); // each color
});
var array = [0,0,0,1,0,0,0];
var pass = loop(array, function(val) {
if (val!=0) return false;
});
// below will log failed
if (pass) zog("passed"); // by default loop returns true (as of ZIM 10.6.1)
else zog("failed"); // false inside loop gets assigned to pass
var person = {name:"Dan Zen", occupation:"Inventor", location:"Dundas"}
var result = loop(person, function(prop, val, index, total, start, end, object) { // do not have to collect all these
zog(prop, val); // each key value pair
if (val == "criminal") return "criminal"; // this would return out of the loop to the containing function
});
if (result == "criminal") alert("oh no!");
var tags = zet(".heading").tags; // get an NodeList of tags styled with heading class
loop(tags, function(tag, i) {
tag.innerHTML = i + ". " + tag.innerHTML; // add an index number in front
});
END EXAMPLE
PARAMETERS supports DUO - parameters or single object with properties below
obj - a Number of times to loop or an Array or Object or NodeList to loop through
call - the function to call
the function will receive (as its final parameters) the index, total, start, end, obj
where the index is the current index, total is how many times the loop will run
start is the start index, end is the end index and obj is the object passed to the loop
the starting parameters vary depending on the type of obj:
if the obj is a number then the first parameter is the index (no extra starting parameters given)
if the obj is an array then the first parameter is the element at the current index
if the obj is an object literal then the first and second parameters are the property name and property value at the current index
reverse - (default false) set to true to run the loop backwards to 0
step - (default 1) each step will increase by this amount (positive whole number - use reverse to go backwards)
start - (default 0 or length-1 for reverse) index to start
end - (default length-1 or 0 for reverse) index to end
RETURNS any value returned from the loop - or true if no value is returned from a loop
--*///+9.5
zim.loop = function(obj, call, reverse, step, start, end) {
var sig = "obj, call, reverse, step, start, end";
var duo; if (duo = zob(zim.loop, arguments, sig)) return duo;
z_d("9.5");
if (zot(obj) || zot(call)) return undefined;
if (zot(reverse)) reverse = false;
if (zot(step) || step <= 0) step = 1;
var type = typeof obj=="number"?"number":(obj.constructor === Array?"array":(obj.constructor === {}.constructor?"object":(obj instanceof NodeList?"nodelist":(obj instanceof HTMLCollection?"htmlcollection":"invalid"))));
if (type == "invalid") {
return undefined;
}
if (type == "number" || type == "array" || type == "nodelist" || type == "htmlcollection") {
var length = type=="number"?obj:obj.length;
var total = getTotal(length-1);
if (total == 0) return true;
if (reverse) {
for(var i=start; i>=end; i-=step) {
if (type=="number") {
var r = call(i, total, start, end, obj);
} else if (type=="array") {
var r = call(obj[i], i, total, start, end, obj);
} else { // nodelist
var r = call(obj.item(i), i, total, start, end, obj);
}
if (typeof r != 'undefined') return r;
}
} else {
for(var i=start; i<=end; i+=step) {
if (type=="number") {
var r = call(i, total, start, end, obj);
} else if (type=="array") {
var r = call(obj[i], i, total, start, end, obj);
} else { // nodelist or htmlcollection
var r = call(obj.item(i), i, total, start, end, obj);
}
if (typeof r != 'undefined') return r;
}
}
return true
} else if (type == "object") {
var length = 0;
var props = [];
for (var i in obj) {
length++;
props.push(i);
}
var total = getTotal(length-1);
if (total == 0) return;
if (reverse) {
for(var i=start; i>=end; i-=step) {
var r = call(props[i], obj[props[i]], i, total, start, end, obj);
if (typeof r != 'undefined') return r;
}
} else {
for(var i=start; i<=end; i+=step) {
var r = call(props[i], obj[props[i]], i, total, start, end, obj);
if (typeof r != 'undefined') return r;
}
}
return true;
}
function getTotal(max) {
if (zot(start)) start = reverse?max:0;
if (zot(end)) end = reverse?0:max;
if ((reverse && end > start) || (!reverse && start > end)) return 0;
if ((start < 0 && end) <0 || (start > max && end > max)) return 0;
start = Math.max(0, Math.min(start, max));
end = Math.max(0, Math.min(end, max));
return Math.floor((reverse?(start-end):(end-start)) / step) + 1;
}
}//-9.5
/*--
zim.timeout = function(time, call, pauseOnBlur)
timeout
zim function
DESCRIPTION
Calls a function after the time delay - like window.setTimeout()
Uses window.requestAnimationFrame() that tends to rest when the window is not showing
NOTE: setTimeout has the time parameter last, timeout has it first
so that it is consistent with loop() and the CreateJS on() method
NOTE: to clear a timeout you use returnID.clear() - different than window.clearTimeout(returnID)
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
timeout(1000, function(){
circle.x += 100;
stage.update();
});
// moves the circle 100 pixels after one second
// GAME to press button within one second:
var timeout = timeout(1000, function() {
zog("you lose!");
button.enabled = false;
});
var button = new Button().center(stage);
button.on("click", function() {
zog("you win!");
timeout.clear();
});
END EXAMPLE
PARAMETERS
** supports VEE - parameters marked with ZIM VEE mean a zim Pick() object or Pick Literal can be passed
Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
time - |ZIM VEE| milliseconds to wait until function is called
call - function to call when the time passes - will receive the id object as a single parameter
pauseOnBlur - (default false) set to true to pause timeout when window is reduced or another tab gains focus
RETURNS a ZIM timeoutObject to pause and clear the timeout with the following methods and properties:
METHODS - of ZIM timeoutObject
pause(state, immediate, restart) - (default true) will pause the timeout - set to false to unpause the timeout at the time remaining
immediate (default false) set to true to make the timeout function run right away when unpausing (no effect when pausing)
reset (default false) set to true to set the timeout back to 0 time passed when unpausing (no effect when pausing)
clear() - will clear the timeout
PROPERTIES - of ZIM timeoutObject
time - the time in milliseconds that has lapsed
paused - the paused state of the timeout
done - true if finished
--*///+9.7
zim.timeout = function(time, call, pauseOnBlur) {
z_d("9.7");
if (zot(call)) return;
if (typeof call != 'function') return;
if (zot(time)) time = 1000;
time = zim.Pick.choose(time);
var obj = {startTime:Date.now(), time:0, paused:false, done:false};
if (pauseOnBlur) {
if (zot(zim.blurCheck)) zim.setBlurDetect();
zim.pauseOnBlur.push(obj);
}
var lastTime = obj.startTime;
function next() {
var now = Date.now()
obj.time += now - lastTime;
lastTime = now;
if (obj.time >= time) {
obj.done = true;
(call)(obj);
obj.clear();
return;
}
obj.rid = requestAnimationFrame(next);
}
obj.pause = function(state, immediate, reset) {
if (zot(state)) state = true;
if (state) { // pausing
cancelAnimationFrame(obj.rid);
} else { // unpausing
if (immediate) lastTime = 0; // a long time ago ;-)
else if (reset) {lastTime = Date.now(); obj.time=0}
else lastTime = Date.now();
next();
}
obj.paused = state;
}
obj.clear = function() {
if (obj) cancelAnimationFrame(obj.rid);
for (var i in obj) {
delete obj[i];
}
obj.pause = function() {};
obj.clear = function() {};
}
next(); // thanks StevenWarren for the glitch fix!
return obj;
}//-9.7
/*--
zim.interval = function(time, call, total, immediate, pauseOnBlur)
interval
zim function
DESCRIPTION
Calls a function after each time delay - like window.setInterval().
Can pass in an Array of two times to set random time delays each interval.
Can pass in how many times you want to run the function and whether it runs right away.
Uses window.requestAnimationFrame() that tends to rest when the window is not showing.
NOTE: setInterval has the time parameter last, interval has it first
so that it is consistent with loop() and the CreateJS on() method
NOTE: to clear a interval you use intervalObj.clear() - different than window.clearInterval(returnID)
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
interval(1000, function(){
circle.x += 100;
stage.update();
});
// every second the circle will move 100 pixels
// if you want smooth movement, use:
Ticker.add(function() {
circle.x += 100; // no need for stage.update()
});
interval(1000, function(obj) {
zog("counting " + obj.count); // starts counting at 1
if (obj.count == 10) obj.clear(); // will now log 1 to 10
});
OR better:
interval(1000, function(obj) {
zog("counting " + obj.count); // starts counting at 1
}, 10); // now will log 1 - 10 with total parameter set to 10
IMMEDIATE:
interval(1000, function(obj) {
zog("counting " + obj.count); // starts counting at 0
}, 10, true); // now will log 0 - 9 with immediate parameter set to true
EXTERNAL control:
var interval = interval(1000, function() {
zog("counting " + interval.count); // starts counting at 1
});
var button = new Button({label:"STOP", toggle:"START"}).center(stage);
button.on("click", function(){interval.pause(button.toggled);});
RANDOM intervals with ZIM Pick() literals
interval({min:200, max:800}, dropBombs); // bombs will fall at different rates between 200ms and 800ms
interval([1000, 2000], dropBombs); // bombs will fall at either 1000 or 2000 ms
var count = 1;
function increase() {return ++count*1000}
interval(increase, dropBombs); // bombs will fall at 1000, then again after 2000 more ms and 3000 ms more after that, etc.
END EXAMPLE
PARAMETERS
** supports VEE - parameters marked with ZIM VEE mean a zim Pick() object or Pick Literal can be passed
Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
time - |ZIM VEE| (default 1000) milliseconds for the interval (delay until the function runs - again and again)
call - function to call when the interval passes
Will be passed a ZIM intervalObject as a single parameter
This is the same as the return object from animate()
See the Returns section below for methods and properties of the intervalObject
total - (default null - infinite) the number of times the function is called
note: the count property counts intervals but the total property is based on function calls.
The total will be equal to the end count with the immediate parameter set to false (default)
but the total will be one less than the count if the immediate parameter is true (like an Array index and length)
immediate - (default false) set to true to call the function right away (and then still call every interval)
This will not increase the count in the intervalObject because count counts intervals not function calls
Use the provided parameter of the call function to access the intervalObject inside the call function
pauseOnBlur - (default false) set to true to pause interval when window is reduced or another tab gains focus
RETURNS a ZIM intervalObject to pause and clear the interval with the following methods and properties:
METHODS - of ZIM intervalObject
pause(state, immediate, reset) - (default true) will pause the interval - set to false to unpause the interval with time left
immediate (default false) set to true to make the interval function run right away when unpausing (no effect when pausing)
reset (default false) set to true to set the interval back to 0 time passed when unpausing (no effect when pausing)
clear() - will clear the interval
PROPERTIES - of ZIM intervalObject
time - |ZIM VEE| get or set the time for the interval (see time parameter)
count - get the number of times the interval has run (if immediate is true, the first count is 0)
total - get or set the number of times the interval will run if the total parameter is set - otherwise -1 for infinite
paused - get the paused state of the interval (see pause() method)
pauseTimeLeft - if paused, get how much time is left once unpaused
--*///+9.8
zim.interval = function(time, call, total, immediate, pauseOnBlur) {
z_d("9.8");
if (zot(call)) return;
if (typeof call != 'function') return;
if (zot(time)) time = 1000;
if (zot(immediate)) immediate = false;
if (!zot(total) && (isNaN(total) || total<=0)) return;
if (zot(total)) total = -1;
var obj = {count:0, total:total, paused:false, time:time, active:true};
if (pauseOnBlur) {
if (zot(zim.blurCheck)) zim.setBlurDetect();
zim.pauseOnBlur.push(obj);
}
function interval() {
obj.startTime = Date.now();
obj.interval = zim.Pick.choose(obj.time);
obj.id = setTimeout(function() {
if (obj.paused) return;
if (!obj.active) return;
// obj.rid = requestAnimationFrame(interval);
obj.count++;
(call)(obj);
interval();
checkTotal();
}, obj.interval);
}
if (immediate) {
setTimeout(function() {
(call)(obj);
checkTotal();
}, 10);
}
function checkTotal() {
if (total == -1) return;
if (obj.count >= (immediate?obj.total-1:obj.total)) obj.clear();
}
var pausedTimeout;
obj.pause = function(state, immediate, reset) {
if (zot(state)) state = true;
if (state) { // pausing
clearTimeout(pausedTimeout);
clearTimeout(obj.id);
cancelAnimationFrame(obj.rid);
obj.pauseTimeLeft = obj.interval - (Date.now()-obj.startTime);
} else { // unpausing
if (!obj.paused) obj.pause(true);
pausedTimeout = setTimeout(function() {
obj.count++;
(call)(obj);
interval();
checkTotal();
}, immediate?0:reset?obj.interval:obj.pauseTimeLeft);
obj.pauseTimeLeft = null;
}
obj.paused = state;
}
obj.clear = function() {
obj.active = false;
clearTimeout(pausedTimeout);
cancelAnimationFrame(obj.rid);
clearTimeout(obj.id);
var count = obj.count;
for (var i in obj) {
delete obj[i];
}
obj.active = false;
obj.count = count;
obj.pause = function() {};
obj.clear = function() {};
}
interval();
return obj;
}//-9.8
/*--
zim.async = function(url, callback, callbackString)
async
zim function
DESCRIPTION
A way to send data back and forth to a server script without reloading the HTML page.
(like AJAX but without the bother)
Uses a dynamic script call with an optional callback (cross domain calls are okay)
also known as JSON-P pattern but JSON is unnecessary - note, no JSON in two of the examples below.
Pass a url to the server script (ie. php or node page)
and an optional callback function that you define in your code (cannot be an anonymous function).
async will automatically add a random number to the end of your script call to defeat cache.
NOTE: async uses GET so data is limited to GET length (as of ZIM 10 - this is 2K to 8K depending on Browser)
If more data is required, use an AJAX library
NOTE: async uses an r CGI key to send a random number to defeat cache.
Do not send an r property
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// existing JSONp service:
// assuming that we have a callback function called test as shown below
async("http://ip-api.com/json?callback=async.test",test);
function test(data) {zog(data.country);}
// note that the callback we pass the service is async.test not just test
// this allows zim to handle scope issues and garbage collect the dynamic script when done
END EXAMPLE
EXAMPLE
// existing JSON service:
// if the service just returns JSON - then pass through a JSONp wrapper:
var api = "https://swapi.co/api/planets/10/?format=json"; // not JSONp - just JSON
async("https://zimjs.org/cdn/jsonp.php?api="+api+"&callback=async.getData", getData);
function getData(data) {
zog(data); // data will be the JSON parsed object
}
See a full example here: https://codepen.io/danzen/pen/gNKQYY
Here is the jsonp.php code if you would like to host:
END EXAMPLE
EXAMPLE
// CLIENT - your own server script:
// assuming we have a callback function called myFunction as shown below
async("http://yourserver.com/script.php?id=72&name=dan", myFunction);
function myFunction(data){zog(data);}
// SERVER - your script must output the following format as a string:
// "async.myFunction(somedata)"
// in the php file we would use:
header('Content-type: text/javascript');
echo "async.myFunction('success')";
// to return an object literal with nodejs express for example, you would use:
res.send('async.myFunction({list:[1,2,3], name:"whatever"})');
// the data parameter in the myFunction function defined earlier would be an object literal
// we could then do zog(data.list[0]) to log the value 1, etc.
END EXAMPLE
PARAMETERS
url - url to the server script (ie. php or node page)
Note: async uses an r CGI key to send a random number to defeat cache - do not send an r property
callback - (default null) callback function that you define in your code (cannot be an anonymous function)
callbackString - (default null) a string name matching the function in case the file is minified
calling the return function on async does two things:
1. it handles scope issues so we can find your callback function
2. it handles garbage collection to remove the dynamic script tag that was used
if you do not specify a callback function then just send "" back from your server script
NOTE: we have experienced duplicate script calls if nothing is sent back
NOTE: if more than one async() with the same named call function is run at the same time
then a queue of callbacks is created
if the data comes back in a different order, the wrong call could be called
if there is danger of this happening (rare) then use ZIM Ajax
RETURNS undefined
--*///+29
zim.async = function (url, callback, callbackString) {
z_d("29");
if (zot(url)) return;
var tag = document.createElement("script");
if (callback) {
if (callbackString) var n = callbackString;
else var n = callback.toString().split(/\n/,1)[0].match(/^function\s?([^\s(]*)/)[1];
// create a queue if more than one async() to same callback function name
// if data is not returned in same order made, the wrong callbacks may be called
if (!zim.asyncList) zim.asyncList = {};
if (!zim.asyncList[n]) zim.asyncList[n] = [];
zim.asyncList[n].push(callback);
// create callback bridge on async function object
zim.async[n] = function() { // closure to access tag on callback bridge
var t = tag;
var name = n;
return function(d){
if (zim.asyncList[n]) callback = zim.asyncList[n].shift();
if (typeof callback == "function") callback(d);
// remove the script tag
if (t) t.parentNode.removeChild(t); t = null;
}
}();
} else {
if (zim.async.z_s && zim.async.z_s.parentNode) zim.async.z_s.parentNode.removeChild(zim.async.z_s); // keep overwriting same script tag if no callback
zim.async.z_s = tag;
}
if (!url.match(/\?/)) url += "?";
tag.setAttribute("src", url + "&r="+Math.random());
document.getElementsByTagName("head")[0].appendChild(tag);
}//-29
//
/*--
zim.couple = function(json)
couple
zim function
DESCRIPTION
Turns a nested JSON object into a single layer JSON object
The object will have _ between the id and the property name
eg. {"circle":{"x":"10", "y":"20"},"count":{"currentValue":"0"}}
is: {"circle_x":"10", "circle_y":"20", "count_currentValue":"0"}
This allows data to be JSON decoded on the server
and put more directly into table fields of the database
See also ZIM decouple()
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// note the two levels of nesting - this is the format of ZIM Bind data for instance
var test = JSON.stringify({circle:{x:10, y:20},count:{currentValue:0}});
zog(couple(test)); // {"circle_x":"10", "circle_y":"20", "count_currentValue":"0"}
END EXAMPLE
PARAMETERS
json - a JSON string in the nested form of:
{"obj1":{"prop1":"val", "prop2":"val"},"obj2":{"prop3":"val"}}
RETURNS a JSON string with one less level of objects in form of:
{"obj1_prop1":"val", "obj1_prop2":"val", "obj2_prop3":"val"}
--*///+29.2
zim.couple = function (json) {
z_d("29.2");
if (!zim.isJSON(json)) return json;
var obj = JSON.parse(json);
var obj2 = {};
for (var i in obj) {
var o = obj[i];
for (var j in o) {
obj2[i+"_"+j] = o[j];
}
}
return JSON.stringify(obj2);
}//-29.2
/*--
zim.decouple = function(json)
decouple
zim function
DESCRIPTION
Turns a flat coupled JSON object into a nested layer JSON object
The object will remove _ from between the id and the property name
eg. {"circle_x":"10", "circle_y":"20", "count_currentValue":"0"}
is: {"circle":{"x":"10", "y":"20"},"count":{"currentValue":"0"}}
This allows data from table fields of the database
to be more easily dealt with as objects with their own properties
See also ZIM couple()
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// note the two levels of nesting - this is the format of ZIM Bind data for instance
var test = {circle:{x:10, y:20},count:{currentValue:0}};
var test2 = JSON.stringify(test);
var test3 = couple(test);
// {"circle_x":"10", "circle_y":"20", "count_currentValue":"0"}
// send this to server to store in fields
// receive back similar coupled data from fields
// decouple the data:
var test4 = decouple(test3);
// {"circle":{"x":"10", "y":"20"},"count":{"currentValue":"0"}}
var test5 = JSON.parse(test4); // similar object to test!
// {circle:{x:10, y:20},count:{currentValue:0}};
END EXAMPLE
PARAMETERS
json - a JSON string in the coupled form of
{"obj1_prop1":"val", "obj1_prop2":"val", "obj2_prop3":"val"}
RETURNS a JSON string with one less level of objects in the form of:
{"obj1":{"prop1":"val", "prop2":"val"},"obj2":{"prop3":"val"}}
the original JSON string will be returned if the initial JSON string is not coupled
--*///+29.3
zim.decouple = function (json) {
z_d("29.3");
if (!zim.isJSON(json)) return json;
var obj = JSON.parse(json);
var obj2 = {};
for (var i in obj) {
var n = i.split("_", 2);
if (n.length != 2) return json;
if (!obj2[n[0]]) obj2[n[0]] = {};
obj2[n[0]][n[1]] = obj[i];
}
return JSON.stringify(obj2);
}//-29.3
/*--
zim.convertColor = function(color, toColorType, alpha)
convertColor
zim function
DESCRIPTION
Converts color to hex numbers - for example: "#333333"
Or converts color to HTML string - for example: "red"
Or converts color to RGB - for example: "rgb(0,0,0)"
Or converts color to RGBA - for example: "rgba(0,0,0,.5)"
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var color = convertColor("red"); // result is "#ff0000"
var color = convertColor("rgb(255,0,0)")); // result is "#ff0000"
var color = convertColor("rgb(0,0,255)", "string"); // result is "blue"
var color = convertColor("rgb(0,0,20)", "string"); // result is "#000014" - no matching string color
var color = convertColor("#ff0000", "string"); // result is "red"
var color = convertColor("f00", "string"); // result is "red" - note missing # okay and can use three digits
var color = convertColor(blue, "rgba", .5); // result is "rgba(80,196,183,0.5)"
var color = convertColor("rgb(256,256,0)", "rgba", .3); // result is "rgba(256,256,0,.3)"
var color = convertColor("rgba(0,0,0,.2)", anyType, .5); // result is "rgba(0,0,0,.5)"
END EXAMPLE
PARAMETERS
color - (default black) the HTML string or hex color (case insensitive)
"rgba()" to hex will ignore alpha
toColorType - (default "hex") or use "string", "rgb" or "rgba"
if "string" and color does not match existing HTML string color
then will return hex number as string
alpha - (default 1) the alpha used for the "rgba" toColorType
RETURNS a String with the converted color
--*///+27.5
zim.convertColorCheck = false;
zim.convertColor = function(color, toColorType, alpha) {
if (!zim.convertColorCheck) {z_d("27.5"); zim.convertColorCheck=true;}
if (zot(toColorType)) toColorType = "hex";
if (zot(color)) return;
var colors = ['black','aliceblue','antiquewhite','aqua','aquamarine','azure','beige','bisque','blanchedalmond','blue','blueviolet','brown','burlywood','cadetblue','chartreuse','chocolate','coral','cornflowerblue','cornsilk','crimson','cyan','darkblue','darkcyan','darkgoldenrod','darkgray','darkgrey','darkgreen','darkkhaki','darkmagenta','darkolivegreen','darkorange','darkorchid','darkred','darksalmon','darkseagreen','darkslateblue','darkslategray','darkslategrey','darkturquoise','darkviolet','deeppink','deepskyblue','dimgray','dimgrey','dodgerblue','firebrick','floralwhite','forestgreen','fuchsia','gainsboro','ghostwhite','gold','goldenrod','gray','grey','green','greenyellow','honeydew','hotpink','indianred','indigo','ivory','khaki','lavender','lavenderblush','lawngreen','lemonchiffon','lightblue','lightcoral','lightcyan','lightgoldenrodyellow','lightgray','lightgrey','lightgreen','lightpink','lightsalmon','lightseagreen','lightskyblue','lightslategray','lightslategrey','lightsteelblue','lightyellow','lime','limegreen','linen','magenta','maroon','mediumaquamarine','mediumblue','mediumorchid','mediumpurple','mediumseagreen','mediumslateblue','mediumspringgreen','mediumturquoise','mediumvioletred','midnightblue','mintcream','mistyrose','moccasin','navajowhite','navy','oldlace','olive','olivedrab','orange','orangered','orchid','palegoldenrod','palegreen','paleturquoise','palevioletred','papayawhip','peachpuff','peru','pink','plum','powderblue','purple','rebeccapurple','red','rosybrown','royalblue','saddlebrown','salmon','sandybrown','seagreen','seashell','sienna','silver','skyblue','slateblue','slategray','slategrey','snow','springgreen','steelblue','tan','teal','thistle','tomato','turquoise','violet','wheat','white','whitesmoke','yellow','yellowgreen'];
var hex = ['000000','f0f8ff','faebd7','00ffff','7fffd4','f0ffff','f5f5dc','ffe4c4','ffebcd','0000ff','8a2be2','a52a2a','deb887','5f9ea0','7fff00','d2691e','ff7f50','6495ed','fff8dc','dc143c','00ffff','00008b','008b8b','b8860b','a9a9a9','a9a9a9','006400','bdb76b','8b008b','556b2f','ff8c00','9932cc','8b0000','e9967a','8fbc8f','483d8b','2f4f4f','2f4f4f','00ced1','9400d3','ff1493','00bfff','696969','696969','1e90ff','b22222','fffaf0','228b22','ff00ff','dcdcdc','f8f8ff','ffd700','daa520','808080','808080','008000','adff2f','f0fff0','ff69b4','cd5c5c','4b0082','fffff0','f0e68c','e6e6fa','fff0f5','7cfc00','fffacd','add8e6','f08080','e0ffff','fafad2','d3d3d3','d3d3d3','90ee90','ffb6c1','ffa07a','20b2aa','87cefa','778899','778899','b0c4de','ffffe0','00ff00','32cd32','faf0e6','ff00ff','800000','66cdaa','0000cd','ba55d3','9370db','3cb371','7b68ee','00fa9a','48d1cc','c71585','191970','f5fffa','ffe4e1','ffe4b5','ffdead','000080','fdf5e6','808000','6b8e23','ffa500','ff4500','da70d6','eee8aa','98fb98','afeeee','db7093','ffefd5','ffdab9','cd853f','ffc0cb','dda0dd','b0e0e6','800080','663399','ff0000','bc8f8f','4169e1','8b4513','fa8072','f4a460','2e8b57','fff5ee','a0522d','c0c0c0','87ceeb','6a5acd','708090','708090','fffafa','00ff7f','4682b4','d2b48c','008080','d8bfd8','ff6347','40e0d0','ee82ee','f5deb3','ffffff','f5f5f5','ffff00','9acd32'];
if (toColorType.toLowerCase() == "zim") {
var i = zim.colorsHex.indexOf(color);
if (i<0) return color;
return zim.colors[zim.colorsHex.indexOf(color)];
}
var answer;
if (answer = color.match(/rgba\((.*)\)/)) {
if (zot(alpha)) {
color = "rgb("+answer[1]+")"; // includes alpha but does not matter
} else {
var c = color.split(",");
c[3] = alpha+")";
return c.join(",");
}
}
function rgbToHex(rgb) {
var hex = Number(rgb).toString(16);
if (hex.length < 2) {
hex = "0" + hex;
}
return hex;
};
function getRGB(string) {
var c = string.split(",");
var red = rgbToHex(c[0]);
var green = rgbToHex(c[1]);
var blue = rgbToHex(c[2]);
return [red, green, blue];
}
if (zot(alpha)) alpha == 1;
if (answer = color.match(/rgb\((.*)\)/)) {
if (toColorType == "rgba") {
var c = color.split(")");
return c[0]+","+alpha+c[1];
} else if (toColorType == "hex") {
var colors = getRGB(answer[1]);
return "#" + colors[0] + colors[1] + colors[2];
} else if (toColorType == "string") {
var color = getRGB(answer[1]).join("").toLowerCase();
var index = hex.indexOf(color);
if (index == -1) return "#" + color;
else return colors[index];
} else return color;
}
if (toColorType == "rgb" || toColorType == "rgba") {
function hexToRgbA(hex){ // kennebec on StackOverflow
var c;
if(/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)){
c= hex.substring(1).split('');
if(c.length== 3){
c= [c[0], c[0], c[1], c[1], c[2], c[2]];
}
c= '0x'+c.join('');
if (toColorType == "rgb") {
return 'rgb('+[(c>>16)&255, (c>>8)&255, c&255]+')';
} else {
return 'rgba('+[(c>>16)&255, (c>>8)&255, c&255].join(',')+','+alpha+')';
}
} else {
if (toColorType == "rgb") {
return "rgb(0,0,0)";
} else {
return "rgba(0,0,0,1)";
}
}
}
if (color.charAt(0)=="#") {
return hexToRgbA(color);
} else {
return hexToRgbA(zim.convertColor(color));
}
} else if (toColorType == "hex") {
if (color.charAt(0)=="#") return color; // already hex
} else {
if (color.charAt(0)=="#") {
color = color.replace("#","");
if (color.length == 3) {
color = color.charAt(0)+color.charAt(0)+color.charAt(1)+color.charAt(1)+color.charAt(2)+color.charAt(2);
}
}
}
if (toColorType == "string") {
var index = hex.indexOf(color);
if (index == -1) return "#" + color;
else return colors[index];
} else {
return "#"+hex[colors.indexOf(color.toLowerCase())!=-1?colors.indexOf(color):0];
}
}//-27.5
/*--
zim.colorRange = function(color1, color2, ratio)
colorRange
zim function
DESCRIPTION
Gets the color in a range between two colors based on a ratio from 0-1
Used internally by setColorRange() method and colorRange property of ZIM shapes
including animating color from current color to a new color
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
zog(colorRange(green, blue, .5)); // #7ecb7c
var rect = new Rectangle(100,100,red).center().setColorRange(purple);
rect.colorRange = .1; will change color to #f1455e (closer to red than purple)
rect.animate({color:purple}, 1000); // will animate color to purple in one second
rect.wiggle("colorRange", .5, .2, .5, 1000, 5000); // wiggles the color in the range
END EXAMPLE
PARAMETERS
color1 - (default null) the first color as an HTML string or hex color (case insensitive)
color2 - (default black) the second color as an HTML string or hex color (case insensitive)
ratio - (default .5) the ratio where 0 is the first color and 1 the second color
RETURNS a hex color string
--*///+27.6
zim.colorRangeCheck = false;
zim.colorRange = function(color1, color2, ratio) {
if (!zim.colorRangeCheck) {z_d("27.6"); zim.colorRangeCheck=true;}
// thanks Chris Dolphin - StackOverflow
// modified by Dan Zen to use hex input and output
// possibly converting and converting back - but not quite...
if (zot(ratio)) ratio = .5;
ratio = Math.max(0, Math.min(1, ratio));
if (zot(color1)) color1 = "white";
if (zot(color2)) color2 = "black";
var c1 = zim.convertColor(color1, "rgb");
var c2 = zim.convertColor(color2, "rgb");
var color1 = c1.substring(4, c1.length - 1).split(',');
var color2 = c2.substring(4, c2.length - 1).split(',');
var difference;
var newColor = "#";
var c;
for (var i=0; i{
// let r,g,b,P,f,t,h,i=parseInt,m=Math.round,a=typeof(c1)=="string";
// if(typeof(p)!="number"||p<-1||p>1||typeof(c0)!="string"||(c0[0]!='r'&&c0[0]!='#')||(c1&&!a))return null;
// if(!this.pSBCr)this.pSBCr=(d)=>{
// let n=d.length,x={};
// if(n>9){
// [r,g,b,a]=d=d.split(","),n=d.length;
// if(n<3||n>4)return null;
// x.r=i(r[3]=="a"?r.slice(5):r.slice(4)),x.g=i(g),x.b=i(b),x.a=a?parseFloat(a):-1
// }else{
// if(n==8||n==6||n<4)return null;
// if(n<6)d="#"+d[1]+d[1]+d[2]+d[2]+d[3]+d[3]+(n>4?d[4]+d[4]:"");
// d=i(d.slice(1),16);
// if(n==9||n==5)x.r=d>>24&255,x.g=d>>16&255,x.b=d>>8&255,x.a=m((d&255)/0.255)/1000;
// else x.r=d>>16,x.g=d>>8&255,x.b=d&255,x.a=-1
// }return x};
// h=c0.length>9,h=a?c1.length>9?true:c1=="c"?!h:false:h,f=this.pSBCr(c0),P=p<0,t=c1&&c1!="c"?this.pSBCr(c1):P?{r:0,g:0,b:0,a:-1}:{r:255,g:255,b:255,a:-1},p=P?p*-1:p,P=1-p;
// if(!f||!t)return null;
// if(l)r=m(P*f.r+p*t.r),g=m(P*f.g+p*t.g),b=m(P*f.b+p*t.b);
// else r=m((P*f.r**2+p*t.r**2)**0.5),g=m((P*f.g**2+p*t.g**2)**0.5),b=m((P*f.b**2+p*t.b**2)**0.5);
// a=f.a,t=t.a,f=a>=0||t>=0,a=f?a<0?t:t<0?a:a*P+t*p:0;
// if(h)return"rgb"+(f?"a(":"(")+r+","+g+","+b+(f?","+m(a*1000)/1000:"")+")";
// else return"#"+(4294967296+r*16777216+g*65536+b*256+(f?m(a*255):0)).toString(16).slice(1,f?undefined:-2)
// }
/*--
zim.lighten = function(color, ratio)
lighten
zim function
DESCRIPTION
Lightens the color by a ratio from 0 to 1
A shortcut for ZIM colorRange(color, white, ratio);
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// make a slightly lighter than ZIM blue circle
new Circle(100, lighten(blue, .2)).center();
END EXAMPLE
PARAMETERS
color - the color as an HTML string or hex color (case insensitive)
ratio - (default .5) the ratio where 0 is the color and 1 white
RETURNS a hex color string
--*///+27.65
zim.lightenCheck = false;
zim.lighten = function(color, ratio) {
if (!zim.lightenCheck) {z_d("27.65"); zim.lightenCheck=true;}
return zim.colorRange(color, "#FFFFFF", ratio);
}//-27.65
/*--
zim.darken = function(color, ratio)
darken
zim function
DESCRIPTION
Darkens the color by a ratio from 0 to 1
A shortcut for ZIM colorRange(color, black, ratio);
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// make a slightly darker than ZIM blue circle
new Circle(100, darker(blue, .2)).center();
END EXAMPLE
PARAMETERS
color - the color as an HTML string or hex color (case insensitive)
ratio - (default .5) the ratio where 0 is the color and 1 black
RETURNS a hex color string
--*///+27.66
zim.darkenCheck = false;
zim.darken = function(color, ratio) {
if (!zim.darkenCheck) {z_d("27.66"); zim.darkenCheck=true;}
return zim.colorRange(color, "#000000", ratio);
}//-27.66
/*--
zim.pointAlongCurve = function(points, ratio, getAngle)
pointAlongCurve
zim function
DESCRIPTION
Finds a point along a cubic Bezier curve - such as that used in Blob and Squiggle
as well as the Shape.graphics.bezierCurveTo() or tiny api bt()
Used internally for animating along Blob and Bezier curves
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// point1, control1, control2, point2
var points = [{x:100,y:100}, {x:200,y:100}, {x:200,y:100}, {x:200,y:200}]
var shape = new Shape().addTo();
shape.graphics
.s("black").ss(2)
.mt(points[0].x,points[0].y)
.bt(points[1].x,points[1].y, points[2].x,points[2].y, points[3].x,points[3].y);
new Circle(10,red).loc(pointAlongCurve(points, .2));
END EXAMPLE
PARAMETERS
points - an array of point objects (or objects with an x and y property)
for a cubic Bezier - point1, control1, control2, point2
ratio - (default .5) the ratio where 0 is at the first point and 1 is at the second point
getAngle - (default false) request a calculated angle of tangent at point
even - (default false) use modified cubic equation for even spacing for percentages
even is used by Beads but not by placing a point along a path
RETURNS a point object with x and y properties on the curve at the ratio
as well as an angle property for the tangent if getAngle is true
--*///+27.7
zim.pointAlongCurve = function(points, ratio, getAngle, even) {
z_d("27.7");
if (!points || !points[0] || !points[1] || !points[2] || !points[3]) return;
if (zot(even)) even = false;
var cubic = new zim.Bezier(points[0],points[1],points[2],points[3]);
if (even) {
var x=cubic.mx(ratio);
var y=cubic.my(ratio);
} else {
var x=cubic.x(ratio);
var y=cubic.y(ratio);
}
if (getAngle) {
var lastRatio = ratio-.05;
var nextRatio = ratio+.05;
if (lastRatio < 0) lastRatio = 0;
if (nextRatio > 1) nextRatio = 1;
if (even) {
var x0=cubic.mx(lastRatio);
var y0=cubic.my(lastRatio);
var x2=cubic.mx(nextRatio);
var y2=cubic.my(nextRatio);
} else {
var x0=cubic.x(lastRatio);
var y0=cubic.y(lastRatio);
var x2=cubic.x(nextRatio);
var y2=cubic.y(nextRatio);
}
var angle = zim.angle(x0, y0, x2, y2);
return({x:x,y:y,angle:angle});
}
return({x:x,y:y});
}//-27.7
/*--
zim.distanceAlongCurve = function(points)
distanceAlongCurve
zim function
DESCRIPTION
Finds approximate distance along a cubic Bezier curve - such as that used in Blob and Squiggle
as well as the Shape.graphics.bezierCurveTo() or tiny api bt()
Used internally for animating along Blob and Bezier curves
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// point1, control1, control2, point2
var points = [{x:100,y:100}, {x:200,y:100}, {x:200,y:100}, {x:200,y:200}]
var shape = new Shape();
shape.graphics
.s("black").ss(2)
.mt(points[0].x,points[0].y)
.bt(points[1].x,points[1].y, points[2].x,points[2].y, points[3].x,points[3].y);
zog(distanceAlongCurve(points)); // 170.7
END EXAMPLE
PARAMETERS
points - an array of point objects (or objects with an x and y property)
for a cubic Bezier - point1, control1, control2, point2
RETURNS an approximate distance along the curve
--*///+27.8
zim.distanceAlongCurve = function(points) {
z_d("27.8");
// Thanks David F. Knight in OpenGl.org forumn
// points are [startPt, controlPt1, controlPt2, endPt]
var chord = zim.dist(points[0], points[3]);
var controlDist = zim.dist(points[0], points[1]) + zim.dist(points[1], points[2]) + zim.dist(points[2], points[3]);
return (chord + controlDist)/2;
}//-27.8
/*--
zim.closestPointAlongCurve = function(point, segmentPoints, num, interpolate, percentage)
closestPointAlongCurve
zim function
DESCRIPTION
Finds the closest point along a cubic Bezier curve before the given point.
Blob and Squiggle use cubic Bezier as does the Shape.graphics.bezierCurveTo() or tiny api bt()
Used internally for adding points to a Blob and Bezier curves
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var blob = new Blob().center();
var points = blob.segmentPoints;
stage.on("stagemousedown", function (e) {
var point = blob.globalToLocal(e.stageX, e.stageY)
zog(closestPointAlongCurve({x:point.x, y:point.y}, points))
// gives index of point on curve before mouse location
});
END EXAMPLE
PARAMETERS
point - an object with an x and y property
this could be {x:100, y:140} or circle, etc.
the results tell which segment to add the point to
the segment starting with the returned index
segmentPoints - an array of cubic Bezier point data
each being an array of points for a cubic Bezier
in the format of [point1, control1, control2, point2]
Note, this is not the same as Blob or Squiggle points
but rather use the segmentPoints property of Blob and Squiggle
num - (default 10) the number of points per segment used to calculate answer
interpolate - (default false) will return closest test point - not index of closest existing point
percentage - (default false) will return percent (0-100) the nearest point is on the path (overrides interpolate)
RETURNS the index of the closest point in segmentPoints before the given point
or if interpolate is true, will return the closest testPoint (use higher num for better result)
or if percentage is true, will return percent (0-100) the nearest point is on the path (overrides interpolate)
--*///+27.9
zim.closestPointAlongCurve = function(point, segmentPoints, num, interpolate, percentage) {
z_d("27.9");
var closest = 10000000;
var closestTestPoint;
var index = 0;
var secondaryIndex = 0;
if (zot(num)) num = 10;
zim.loop(segmentPoints, function(points, i, t) {
// add num more points to estimate closest
var cubic = new zim.Bezier(points[0],points[1],points[2],points[3]);
zim.loop(num, function (j, total) {
// var d = zim.dist(point, zim.pointAlongCurve(segmentPoints(that.points[i], that.points[i .5)) {
if (c.toUpperCase) c = c.toUpperCase();
} else {
if (c.toLowerCase) c = c.toLowerCase();
}
id += String(c);
}
return id;
}//-13.5
/*--
zim.swapProperties = function(property, objA, objB)
swapProperties
zim function
DESCRIPTION
Pass in a property as a string and two object references
and this function will swap the property values.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// exchanges the x position of two ZIM circles
swapProperties("x", circle1, circle2); stage.update();
END EXAMPLE
PARAMETERS
property - a String of the property to swap values eg. "alpha"
objA, objB - the objects on which to swap properties
RETURNS Boolean indicating success
--*///+17.1
zim.swapProperties = function(property, objA, objB) {
z_d("17.1");
if (zot(objA) || zot(objB) || zot(objA[property]) || zot(objB[property])) return false;
var temp = objB[property];
objB[property] = objA[property];
objA[property] = temp;
return true;
}//-17.1
/*--
zim.mobile = function(orientation)
mobile
zim function
DESCRIPTION
Detects if app is on a mobile device - if so, returns the mobile device type:
android, ios, blackberry, windows, other (all which evaluate to true) else returns false.
orientation defaults to true and if there is window.orientation then it assumes mobile
BUT this may return true for some desktop and laptop touch screens
so you can turn the orientation check off by setting orientation to false.
If orientation is set to false the check may miss non-mainstream devices
The check looks at the navigator.userAgent for the following regular expression:
/ip(hone|od|ad)|android|blackberry|nokia|opera mini|mobile|phone|nexus|webos/i
Microsoft mobile gets detected by nokia, mobile or phone.
NOTE: See also the ZIM MOBILE constant - this can be set to true or false to override mobile()
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
if (mobile()) {
var pane = new Pane(300, 200, "Desktop Only");
pane.show();
}
END EXAMPLE
PARAMETERS
orientation - (default true) uses window.orientation property to determine mobile
this may call certain touch screens mobile
but setting to false uses a test on mobile names which could be incomplete
RETURNS a String or false
--*///+28
zim.mobile = function(orientation) {
z_d("28");
if (typeof MOBILE != "undefined" && MOBILE!="default") return MOBILE;
if (!zot(zim.MOBILE) && zim.MOBILE!="default") return zim.MOBILE;
if (zot(orientation)) orientation = true;
if (/ip(hone|od|ad)/i.test(navigator.userAgent)) return "ios";
if (/android|nexus/i.test(navigator.userAgent)) return "android";
if (/blackberry/i.test(navigator.userAgent)) return "blackberry";
if (/nokia|phone|mobile/i.test(navigator.userAgent)) return "windows";
if (/opera mini|webos/i.test(navigator.userAgent)) return "other";
if (orientation && window.orientation !== undefined) {
if (/safari/i.test(navigator.userAgent)) return "ios";
return true;
}
return false;
}//-28
//
/*--
zim.vee = function(obj)
vee
zim function
DESCRIPTION
Determines if obj is a ZIM Pick() object or a Pick Literal - used by ZIM VEE parameters
Pick Literal format is [], {min:a, max:b}, function(){}, {noPick:x} or a function(){}
See https://zimjs.com/docs.html?type=Pick
ZIM Pick is a way to pass in dynamic parameters or style properties
This is very handy to pass in a series() function or an array for random pickings, etc.
Used to create dynamic particles with the Emitter or tile specific items in order, etc.
Pick.choose() accepts any value and if not in ZIM Pick format, will just return the object
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var color = [red, green, blue];
// ternary operator - if in Pick format, add "random" else ""
new Label((vee(color)?"random ":"") + "colors").center();
END EXAMPLE
PARAMETERS
orientation - (default true) uses window.orientation property to determine mobile
this may call certain touch screens mobile
but setting to false uses a test on mobile names which could be incomplete
RETURNS a Boolean true if Pick format or false if not (such as just a number, string, new Circle, etc.)
--*///+28.5
zim.vee = function(obj) {
z_d("28.5");
return !zot(obj) && (obj.type == "Pick" || Array.isArray(obj) || (obj.constructor == {}.constructor && (!zot(obj.max) || !zot(obj.noPick))) || typeof obj == "function");
}//-28.5
/*--
zim.extend = function(subclass, superclass, override, prefix, prototype)
extend
zim function - modified CreateJS extend and promote utility methods
DESCRIPTION
For ES5 - place after a sub class to extend a super class.
Extending a super class means that the sub class receives all the properties and methods of the super class.
For example, a ZIM Container() extends a CreateJS Container and then adds more methods and properties
but all the CreateJS Container methods and properties are still there too like x, y, addChild(), etc.
For ES6 - do not use zim.extend() but rather use the built in ES6 structures as follows:
EXAMPLE
// ES6 - do NOT use zim.extend()
class Person() {
constructor () {
zog("I am a person");
}
}
class Woman extends Person { // use JS6 extends keyword
constructor () {
super(); // use JS6 super() to call the Person constructor - will do the zog()
// Woman code
}
}
// ES6 to extend a zim Container for example (do NOT use zim.extend() in ES6)
class ChineseCoin extends Container { // use JS6 extends keyword
constructor () {
super(); // must call the zim Container before using keyword this
new Circle(100, "gold").addTo(this); // this will be the zim Container
new Rectangle(100, 100, "brown").center(this);
}
}
var coin = new ChineseCoin().center(stage); // coin is a zim Container with Circle and Rectangle inside
END EXAMPLE
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// ES5 examples using functions to make classes
// ES5 has no extends keyword and no super keyword so we use zim.extends()
function Person() {
this.talk = function() {
zog("I am a person");
}
}
function Woman() {
this.super_constructor(); // part of the zim.extend() system
}
extend(Woman, Person); // here is the zim.extend() for ES5
var woman = new Woman();
woman.talk();
END EXAMPLE
NOTE: CreateJS display objects require their constructor to be called otherwise it is like quantum entanglement (seriously)
extend() adds access to the super class constructor so it can be called in the subclass as follows:
this.super_constructor();
It also provides access to super class methods that are overridden
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// ES5 example - see the ES6 set of examples for ES6 ;-)
// make a Collection class that will extend a Container
// the Collection class will call the Container constructor
// and override the the ZIM Container center method in the class body
// and override the CreateJS Container addChild method in the prototype
// either method would work in either place - it is often a matter of preference
// but you might need to use a method in the class body to access local variables
// The ZIM extend() method parameter values need to change depending on where you override
// see the comments inline for the instructions
var Collection = function() {
// for CreateJS the super constructor must be run
this.super_constructor();
// override the zim center() method
// methods in the function call that override must be passed in as an array of strings
// to the override parameter of extend() to be able to access the super_method
this.center = function(where) {
this.super_center(where);
this.y -= 50;
}
}
// override the super class addChild() that comes from the CreateJS Container
// methods on the prototype that override are automatically provided a super_method
// unless the prototype parameter of extend() is set to false (default is true)
Collection.prototype.addChild = function(c) {
this.super_addChild(c); // call the super class addChild
zog("added a child to Collection");
}
// make the Collection extend a Container()
// it will receive all the properties and methods of the Container plus its own
extend(Collection, Container, "center"); // or pass an array of overridden methods
// use the Collection
var c = new Collection();
c.addChild(new Rectangle(100, 100, green)); // zogs "added a child to Collection"
c.center(stage); // centers the collection but then offsets it 50 pixels up
END EXAMPLE
NOTE: the superclass constructor is always available as this.prefix_constructor() no matter the override or prototype settings
NOTE: this.prefix_constructor(); should be called at the top of the subclass to avoid problems when multiple copies of object
NOTE: to extend a class that already extends a ZIM class then change the prefix to a unique name:
EXAMPLE
// if we already had the Collection example above and we want to extend that
// then we must use a new prefix when using extend()
var Records = function() {
this.Collection_constructor();
}
extend(Records, Collection, null, "Collection");
// you will still have this.super_center(), this.super_addChild() if needed
// plus any newly overridden methods available as this.Collection_methodName() etc.
var r = new Records();
r.addChild(new Circle(20, pink));
r.super_center(stage); // call the original center (without vertical shift)
// to extend again, use yet another prefix - for example: "Records"
var Jazz = function() {
this.Records_constructor();
}
extend(Jazz, Records, null, "Records");
END EXAMPLE
PARAMETERS supports DUO - parameters or single object with properties below
NOTE: do NOT use zim.extend() with ES6 - see ES6 examples at top instead
subclass - the class to extend
superclass - the class to extend from (an existing class)
override - (default null) an Array of methods (as Strings) to override.
You can override any function by just defining that function in the subclass
the override parameter gives you access to the overridden function in the superclass prototype
only methods on the superclass prototype can be accessed once overridden - not methods in the superclass body
if there is only one method being overridden then a single string is fine ("test" or ["test"] is fine)
any methods passed to this parameter will be given prefix_methodName() access on the sub class (this.prefix_methodName())
where the prefix is below (note, the prototype setting has no bearing on these manual overrides)
this list is only needed for methods in the subclass body
methods assigned to the prototype of the subclass that override are automatically given prefixes
prefix - (default "super") a prefix that will be followed by "_" and then the overridden method name
by default this.super_constructor() would call the super class constructor
if prefix is set to "Person" then this.Person_constructor() would call the super class constructor
the same system is used to call overridden files in override or prototype
prototype - (default true) will search the subclass prototype for overriding methods
the overridden methods are then available as this.prefix_methodName()
set to false to avoid searching the super class for methods overridden by the sub class prototype
just quickens the code minutely if there is no need
NOTE: extend() is included in Distill if DISPLAY, METHODS or FRAME Module classes are used (otherwise NOT included)
RETURNS the subclass
--*///+50.35
zim.extend = function(subclass, superclass, override, prefix, prototype) {
var sig = "subclass, superclass, override, prefix, prototype";
var duo; if (duo = zob(zim.extend, arguments, sig)) return duo;
if (zot(subclass) || zot(superclass)) {
if (zon && subclass!=zim.StageGL) zog("zim.extend() - please supply a class and its superclass");
return;
}
if (zot(prefix)) prefix = "super";
if (zot(override)) override = [];
if (!Array.isArray(override)) override = [override];
if (zot(prototype)) prototype = true;
// modified CreateJS extend() to include any prototype members already added
// see http://www.createjs.com/docs/easeljs/classes/Utility%20Methods.html
var existingP = {};
for (var f in subclass.prototype) Object.defineProperty(existingP,f,Object.getOwnPropertyDescriptor(subclass.prototype, f));
function o() {this.constructor = subclass;}
o.prototype = superclass.prototype;
subclass.prototype = new o();
for (f in existingP) Object.defineProperty(subclass.prototype,f,Object.getOwnPropertyDescriptor(existingP,f));
// modified CreateJS promote() to promote methods other than constructor only if methods is true
// zim does not override with prototypes so it is uneccessary to loop through the super class methods
// added checking an array of string values of methods defined in class (not prototype) that are being overridden
var subP = subclass.prototype;
var supP = (Object.getPrototypeOf&&Object.getPrototypeOf(subP))||subP.__proto__;
if (supP) {
subP[(prefix+="_") + "constructor"] = supP.constructor; // constructor is not always innumerable
var n;
for (var i=0; i 0 && answer != 0) {
// var place = String(answer).indexOf(".");
// var length = String(answer).length;
// if (place < 0) {place = length++; answer+=".";}
// for (var i=0; i 0) {
var place = String(answer).indexOf(".");
var length = String(answer).length;
if (place < 0) {place = length++; answer+=".";}
for (var i=0; i 0) {
// fix this - Dan Zen - negative decimal number problem
if (sign == -1) answer = answer.substr(1,answer.length-1);
var place = String(answer).indexOf(".");
var length = String(answer).length;
var left = (place < 0) ? length : place;
for (var i=0; i 0) && !includeZero && Number(answer) == 0) answer = 0;
if (time) answer = String(answer).replace(".", ":");
return zim.zut(evt) ? answer : null;
}//-13
/*--
zim.sign = function(num)
sign
zim function
DESCRIPTION
returns -1, 0 or 1 depending on whether the number is less than, equal to or greater than 0
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var speed = 20;
zog(sign(speed)); // 1
var speed = 0;
zog(sign(speed)); // 0
var speed = -20;
zog(sSign(speed)); // -1
END EXAMPLE
PARAMETERS
num - the Number to operate on
RETURNS -1, 0 or 1
--*///+13.1
zim.zimSignCheck = false;
zim.sign = function(num) {
if (!zim.zimSignCheck) z_d("13.1");
zim.zimSignCheck = true;
return num?num<0?-1:1:0;
}//-13.1
/*--
zim.constrain = function(num, min, max, negative)
constrain
zim function
DESCRIPTION
returns a number constrained to min and max
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var cirle.x = constrain(circle.x, circle.radius, stageW-circle.radius);
// circle.x will not be smaller than the radius or bigger than stageW-radius
var speed = constrain(speed, minSpeed, maxSpeed, true);
// will confine the speed between minSpeed and maxSpeed if speed is positive
// and confine the speed between -maxSpeed and -minSpeed if the speed is negative
END EXAMPLE
PARAMETERS
num - the number to be constrained
min - (default 0) the minimum value of the return number
max - (default Number.MAX_VALUE) the maximum value of the return number
negative - (default false) allow the negative range of min and max when num is negative
RETURNS num if between min and max otherwise returns min if less or max if greater (inclusive)
RETURNS num between -max and -min if num is negative and negative parameter is set to true
--*///+13.2
zim.constrain = function(num, min, max, negative) {
z_d("13.2");
if (zot(num)) return;
if (zot(min)) min = 0;
if (zot(max)) max = Number.MAX_VALUE;
if (max < min) {max2 = min; max = min; min = max2;} // ES6 Fix to come
if (zot(negative)) negative = false;
if (negative && num < 0) {
return Math.max(-max, Math.min(num, -min));
} else {
return Math.max(min, Math.min(num, max));
}
}//-13.2
/*--
zim.dist = function(a, b, c, d)
dist
zim function
DESCRIPTION
Calculates the distance between two points.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// using point values for each
var p1 = new Point(100, 100); // or {x:100, y:100}
var p2 = new Point(200, 200);
zog(dist(p1, p2)); // 141.42...
END EXAMPLE
EXAMPLE
// using x and y values for each
var distance = dist(stageW/2, stageH/2, frame.mouseX, frame.mouseY);
// distance of mouse from center of stage
END EXAMPLE
PARAMETERS
a - first Point - any object with x and y values - eg. a zim Container or zim Point or {x:10, y:30}
or if four parameter values, an x value of the first point
b - second Point - any object with x and y values
or if four parameter values, a y value of the first point
c - (default null) an x value of a second point - if using x and y values
d - (default null) a y value of a second point - if using x and y values
RETURNS a positive Number that is the distance (could be on an angle)
--*///+13.3
zim.zimDistCheck = false;
zim.dist = function(a, b, c, d) {
if (!zim.zimDistCheck) z_d("13.3");
zim.zimDistCheck = true;
if (zot(a) || zot(b)) return;
if (!zot(a.x) && !zot(b.x)) {
d = b.y;
c = b.x;
b = a.y;
a = a.x;
} else {
if (zot(c)) c = 0;
if (zot(d)) d = 0;
}
return Math.sqrt((Math.pow(c-a, 2) + Math.pow(d-b, 2)));
}//-13.3
//
/*--
zim.rectIntersect = function(a, b, margin)
rectIntersect
zim function
DESCRIPTION
Returns true if two rectangles are intersecting - this is a very fast but exact calculation
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// using point values for each
var r1 = {x:100, y:100, width:300, height:200}
var r2 = new Boundary(50,200,100,100);
zog(rectIntersect(r1, r2)); // true
END EXAMPLE
PARAMETERS
a - first rectangle with x, y, width and height properties - such as a bounds or Boundary
make sure that these are in the same coordinate systems - use ZIM boundsToGlobal for instance
b - second rectangle with x, y, width and height properties
margin - (default 0) positive value adds margin (more likely to intersect) and negative subtracts (less likely to intersect)
RETURNS a Boolean as to whether rectangles are intersecting
--*///+13.32
zim.zimRectIntersectCheck = false;
zim.rectIntersect = function(a, b, margin) {
if (!zim.zimRectIntersectCheck) z_d("13.32");
zim.zimRectIntersectCheck = true;
if (zot(margin)) margin = 0;
if (a.x >= b.x + b.width + margin || a.x + a.width + margin <= b.x ||
a.y >= b.y + b.height + margin || a.y + a.height + margin <= b.y ) {
return false;
} else {
return true;
}
}//-13.32
//
/*--
zim.boundsAroundPoints = function(points)
boundsAroundPoints
zim function
DESCRIPTION
Returns a rectangle {x,y,width,height} around an array of points {x,y}
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var blob = new Blob();
var points = blob.interpolate();
zog(boundsAroundPoints(points)); // {x:-100, y:-100, width:200, height:200}
// could call this after resizing the blob to get the rough bounds of the blob (or squiggle)
// interpolate defaults to 1 so setting 5 would be even more precise, etc.
END EXAMPLE
PARAMETERS
points - an array of points with x and y properties.
RETURNS an object with x, y, width and height properties
representing the rectangle around the points provided
--*///+13.34
zim.zimBoundsAroundPointsCheck = false;
zim.boundsAroundPoints = function(points) {
if (!zim.zimBoundsAroundPointsCheck) z_d("13.34");
zim.zimBoundsAroundPointsCheck = true;
var tX = 10000;
var tY = 10000;
var bX = -10000;
var bY = -10000;
for (var i=0; i bX) bX = p.x;
if (p.y < tY) tY = p.y;
if (p.y > bY) bY = p.y;
}
return {x:tX, y:tY, width:bX-tX, height:bY-tY};
}//-13.34
/*--
zim.angle = function(x1, y1, x2, y2)
angle
zim function
DESCRIPTION
Calculates the angle between two points relative to the positive x axis
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var angle = angle(stageW/2, stageH/2, stageW/2+100, stageH/2+100); // 45
// angle from center of stage to 100, 100 to the right and down from the center of the stage
var angle2 = angle(stageW/2, stageH/2, stageW/2-100, stageH/2+100); // 135
var angle3 = angle(stageW/2, stageH/2, stageW/2+100, stageH/2-100); // 315
END EXAMPLE
PARAMETERS
x1, y1 - first point x and y
unless no second point in which case x1, y1 will be second point and first point will be 0, 0
x2, y2 - second point x and y
RETURNS a positive Number that is the angle between first and second point relative to positive x axis
--*///+13.4
zim.angle = function(x1, y1, x2, y2) {
z_d("13.4");
if (zot(x1) || zot(y1)) return;
if (zot(x2)) {x2 = x1; x1 = 0};
if (zot(y2)) {y2 = y1; y1 = 0};
return (Math.atan2(y2-y1, x2-x1)*180/Math.PI+360*100)%360;
}//-13.4
/*--
TAU, DEG, RAD
TAU, DEG, RAD
zim constants
DESCRIPTION
ZIM degrees and radian constants
If working in radians, TAU is equal to 2 radians (360).
This allows easy visualization of angles - TAU/2 is 180, TAU/4 is 90, etc.
DEG is 180/Math.PI so you multiply a radian value by DEG to get degrees.
RAD is Math.PI/180 so you multiply a degree value by RAD to get radians.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
Math.sin(TAU/4); // sin of 90 degrees (1)
// is same as
Math.sin(90*RAD);
// is same as
Math.sin(90*Math.PI/180);
// and
Math.asin(1)*DEG; // is 90
END EXAMPLE
--*///+83.6
zim.TAU = Math.PI * 2;
zim.DEG = 180/Math.PI;
zim.RAD = Math.PI/180;
//-83.6
/*--
zim.smoothStep = function(num, min, max)
smoothStep
zim function
DESCRIPTION
smoothStep takes an input value and outputs a value between 0 and 1
that represents a transition between the min and max with easing at both ends.
If you want the easing to be more pronounced, then reduce difference between min and max.
If the value falls outside the min or max then it is set to the min or max.
Remember the return value is between 0 and 1 so you can multiply by max-min and add it to min
to get a value at the original scale.
Used to make blobs with Noise(): https://zimjs.com/noise/blobs.html
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// here we use smoothStep to make a gradient between black and white
// not an even one right across but a gradient across a transition zone of 40-100
// create an empty Bitmap size 200, 200 and center it on the stage
var bmp = new Bitmap(null, 200, 200).center(stage);
// we need to loop and get a value for each pixel
// normally we loop across the rows and then do each column
// but here we are making a horizontal gradient
// so we will loop across the x and get the desired value
// then when we loop across the y in the inner loop, we just use that same value
for (var x = 0; x < bmp.width; x++) {
// making gradient in x only so calculate smoothStep here
// x will be from 0 to the width of 200
// we pass in a min of 40 and a max of 100
// the result of smoothStep is between 0 and 1
// so from 0 to 40 the return of smoothStep will be 0
// and from 100 to 200 the return of smoothStep will be 1
// In between, the return value starts off close to 0, then speeds up
// and then slows down to 1 in a curve that is somewhat like the letter f
// When we multiply by 255 and apply that result to each color,
// we get black and then a range of greys and then white
var value = smoothStep(x, 40, 100)*255;
// now we loop down the column for the x position
for (var y = 0; y < bmp.height; y++) {
// imageData is four values per pixel
// the red, green, blue and alpha
// in one big long array - each value will be constrained to between 0 and 255
// this i value will increase by 4 each time
// then we write the same value for red, green, blue to get a shade of grey
var i = (x + y * bmp.width) * 4;
bmp.imageData.data[i] = value; // red (0-255)
bmp.imageData.data[i + 1] = value; // green (0-255)
bmp.imageData.data[i + 2] = value; // blue (0-255)
bmp.imageData.data[i + 3] = 255; // alpha (0-255)
}
}
bmp.drawImageData(); // draw the imageData to the Bitmap
END EXAMPLE
PARAMETERS
num - the input value with respect to min and max
min - the lower edge for smoothStep (often termed edge0) - anything smaller will be set to min
max - the upper edge for smoothStep (often termed edge1) - anything bigger will be set to max
RETURNS a number between 0 and 1 that represents a transition factor
--*///+13.7
zim.smoothStep = function(num, min, max) {
z_d("13.7");
var x = zim.constrain((num - min)/(max - min), 0, 1);
return x*x*x*(x*(x*6 - 15) + 10); // Perlin
}//-13.7
// SUBSECTION CLASSES
/*--
zim.Ajax = function(master, couple, lock)
Ajax
zim class
DESCRIPTION
An AJAX class to send data back and forth to a server without reloading the page
NOTE: also see ZIM async() to send data back and forth as JSONp
using async can avoid various security issues with cross domain access
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// GET - note: GET is limited to approximately 2048 characters
var ajax = new Ajax();
new Button().center().tap(function () {
ajax.get("https://yourserver/ajax.php?record=pressed");
});
END EXAMPLE
EXAMPLE
// GET with user input and server response
var query = new TextArea(300,90).center();
new Button({label:"SUBMIT", corner:5}).sca(.7).pos(0,100,CENTER,CENTER)
.tap(function () {
new Ajax().get("https://yourserver/ajax.php?query="+encodeURI(query.text), callback);
});
function callback(data) {
query.text = "Date: " + data.date + "\nAnswer: " + data.answer;
}
END EXAMPLE
EXAMPLE
// POST - virtually unlimited size
var ajax = new Ajax();
new Button().center().tap(function () {
var data = {name:"Dr Abstract", occupatio:"creator"};
// data will automatically have JSON.stringify() applied
var id = "AB234";
ajax.post("https://yourserver/ajax.php", data, "add", id, callback);
});
function callback(data) {
zog(data.name); // "Dr Abstract"
}
END EXAMPLE
EXAMPLE
// put - sends data in body of content
// same as POST but no command and receive in PHP as follows:
END EXAMPLE
PARAMETERS
master - data to be sent with every get() or post() (not put())
this can be collected in php, for example, as $GET_["master"] or $POST_["master"]
couple - (default false) - set to true to turn nested JSON into a single layer
** for POST only - use ZIM couple() and decouple() manually with GET and PUT
see ZIM couple() and decouple() for more information
data for POST will be coupled when sent and uncoupled when received
lock - (defualt null) send an optional lock id - would need to be processed on the server
METHODS
get(url, call) - send and receive based on GET (approximate limit 2048 characters)
the url will have parameters in cgi format to send information
for example: "server.php?name="+encodeURI("Dr Abstract")+"&occupation=creator";
in PHP access these with $_GET["name"], $_GET["occupation"], etc.
call is the function to call and will receive (data, error) as parameters
the data will automatically have JSON.parse() applied if in JSON format
post(url, data, command, extra, call) - send and receive based on POST
** accepts the ZIM DUO technique of regular parameters or a configuration object with properties matching parameters
url is the url to a server script such as php or node
the url will not need parameters but rather use the data, command and extra
data will automatically have JSON.stringify() applied
in PHP access this with $data = $_POST["data"];
often, we might store this directly as JSON in the database
but it can be split up and put in fields as follows
$assoc = json_decode($data, true); // true for assoc array if desired
command is what to do with the data and will be encodeURI sent as variable command
so for instance receive $command = $_POST["command"];
this could have a value of "select", "add", "update", "delete", etc.
extra is any extra filter information and will be encodeURI sent as variable extra
so for instance receive $extra = $_POST["extra"];
this could be an id or a search term
call is the function to call and will receive (data, error) as parameters
the data will automatically have JSON.parse() applied if in JSON format
put(url, data, call) - send and receive based on PUT
put sends data in the body of the file
the url will not have parameters but rather use the data
the data will automatically have JSON.stringify() applied
in PHP access this with: $array = json_decode(file_get_contents('php://input'), true);
call is the function to call and will receive (data, error) as parameters
the data will automatically have JSON.parse() applied if in JSON format
PROPERTIES
master - get or set the master data being sent with each get() or post() (not put())
couple - get or set whether the POST data is coupled when sent and uncoupled when received (not get() and put())
lock - get or set the lock data being sent with each get() or post() (not put())
--*///+13.8
zim.Ajax = function(master, couple, lock) {
z_d("13.8");
var http = new XMLHttpRequest();
this.master = master;
this.couple = couple;
this.lock = lock;
var that = this;
this.get = function(url, callback) {
// add here in case property is changed
var addMaster = !zot(that.master)?"&master="+encodeURI(master):"";
var addLock = !zot(that.lock)?"&lock="+encodeURI(lock):"";
http.open('GET', url+addMaster+lock, true);
http.onload = function() {
if (http.status==200) {
callback(isJSON(http.responseText)?JSON.parse(http.responseText):http.responseText);
} else {
callback(null, 'Error: '+http.status);
}
}
http.send();
}
this.post = function(url, data, command, extra, callback) {
var sig = "url, data, command, extra, callback";
var duo; if (duo = zob(that.post, arguments, sig)) return duo;
if (zot(url)) return;
http.open('POST', url, true);
http.setRequestHeader('Content-type', "application/x-www-form-urlencoded");
http.onload = function() {
var r = http.responseText;
if (zim.isJSON(r)) {
if (that.couple) r = zim.decouple(r);
r = JSON.parse(r);
}
callback(r);
// callback(isJSON(http.responseText)?JSON.parse(http.responseText):http.responseText);
}
if (!zim.isJSON(data)) data = JSON.stringify(data);
if (that.couple) data = zim.couple(data);
var addMaster = !zot(that.master)?"&master="+encodeURI(master):"";
var addLock = !zot(that.lock)?"&lock="+encodeURI(lock):"";
var addCommand = !zot(command)?"&command="+encodeURI(command):"";
var addExtra = !zot(extra)?"&extra="+encodeURI(extra):"";
http.send("data="+data+addMaster+addLock+addCommand+addExtra);
}
this.put = function(url, data, callback) {
http.open('PUT', url, true);
http.setRequestHeader('Content-type', 'application/json');
http.onload = function() {
callback(isJSON(http.responseText)?JSON.parse(http.responseText):that.http.responseText);
}
http.send(JSON.stringify(data));
}
}//-13.8
/*--
zim.Noise = function(seed)
Noise
zim class
DESCRIPTION
Noise creates OpenSimplex Noise: https://en.wikipedia.org/wiki/OpenSimplex_noise
Converted from https://www.npmjs.com/package/open-simplex-noise
See examples at https://zimjs.com/noise/
In general, this is special noise where the pixels relate to one another in a complex way.
This connection, lets us do things like create terrains or blobs, etc. that look organic.
There is 1D, 2D, 3D, and 4D noise where we pass in one value, two values, three values and four values.
We always get back a number between -1 and 1 and this result relates to the results around it.
1D - we can plot 1D by drawing line segments across the stage (x) and setting the y value to the result of simplex1D(x)
This makes a 2D mountain-like terrain across the stage
2D - if we keep the plot from the 1D but use 2D and change the second parameter, we can animate the line.
We just need to adjust the second parameter by a very small amount each time such as .005.
Or we can plot put the return value of simplex2D onto its x,y matching location in a Bitmap
mapping it to a greyscale to make a traditional noise pattern.
We can adjust the "size" of the noise by dividing the x and y values (frequency).
If we use the ZIM smoothStep() function we can smoothen these to make blobs.
We can also use the return value as height for 3D terrain.
3D - if we keep the traditional noise/blob pattern from the 2D but use simplex3D and animate the third parameter,
we can animate the 2D noise in time which looks great when we animate blobs!
This plotting is thousands of computations and will bog the computer if too big.
4D - will allow us to animate 3D values, etc.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// 1D Noise to make a jagged line across the stage
var noise = new Noise();
var shape = new Shape(stageW, stageH).addTo(stage);
shape.graphics.s("black").ss(2).mt(0, stageH/2);
loop(stageW/50, function(i) {
shape.graphics.lt((i+1)*50, stageH/2 + noise.simplex1D(i)*200);
});
// the above can be animated by using simplex2D and animating the second number by small amounts
END EXAMPLE
EXAMPLE
// 2D noise
// create a Noise object:
var noise = new Noise();
// create an empty Bitmap size 200, 200 into which to draw the noise
var bmp = new Bitmap(null, 200, 200).center(stage);
// we fill the bitmap starting from top left going across in the inner loop,
// then down, then across, etc. until we get to bottom right.
for (var y = 0; y < bmp.height; y++) {
for (var x = 0; x < bmp.width; x++) {
// the noise methods return a number from -1 to 1
// by adding 1 we get a number between 0 and 2 and we divide by 2 to get 0-1
// and we multiply this by 255 to get a number between 0 and 255
var value = (noise.simplex2D(x,y)+1)/2 * 255;
// imageData is one big array with four values per pixel
// the red, green, blue and alpha
// each value will constrained to between 0 and 255
// the i value is how many on the current row plus the columns from the previous rows
// and we set it to increase by 4 each time giving us a place for each color and alpha
// We write the same value for red, green, blue to get a shade of grey
var i = (x + y * bmp.width) * 4;
bmp.imageData.data[i] = value; // red (0-255)
bmp.imageData.data[i + 1] = value; // green (0-255)
bmp.imageData.data[i + 2] = value; // blue (0-255)
bmp.imageData.data[i + 3] = 255; // alpha (0-255)
}
}
bmp.drawImageData(); // this draws the imageData to the Bitmap
// Here is the same example to get blobs using smoothStep:
var f = 25; // try changing this number around
for (var y = 0; y < bmp.height; y++) {
for (var x = 0; x < bmp.width; x++) {
var value = (noise.simplex2D(x/f, y/f)+1)/2; // 0-1
// smoothStep sets less than .3 to 0 and greater than .35 to 1
// and transitions between using an easing formula in the shape of an f
var value = smoothStep(value, .3, .35) * 255;
var i = (x + y * bmp.width) * 4;
bmp.imageData.data[i] = value; // red (0-255)
bmp.imageData.data[i + 1] = value; // green (0-255)
bmp.imageData.data[i + 2] = value; // blue (0-255)
bmp.imageData.data[i + 3] = 255; // alpha (0-255)
}
}
bmp.drawImageData();
END EXAMPLE
PARAMETERS
seed - (default Math.random()*1000000) keeping the same seed can remake a pattern the same
METHODS
simplex1D(x) - returns a noise value between -1 and 1
In each method, the noise value relates to its neighbor rather than a completely random value
simplex2D(x,y) - returns a noise value between -1 and 1
simplex3D(x,y,z) - returns a noise value between -1 and 1
simplex4D(x,y,z,w) - returns a noise value between -1 and 1
PROPERTIES
seed - read only - the seed that was used for the Noise object
--*///+13.9
zim.Noise = function(seed) {
"use strict";
z_d("13.9");
if (zot(seed)) seed = Math.random()*1000000;
var clientSeed = seed;
this.seed = seed;
var that = this;
var con = {}; // holds the constants
con.NORM_2D = 1.0 / 47.0;
con.NORM_3D = 1.0 / 103.0;
con.NORM_4D = 1.0 / 30.0;
con.SQUISH_2D = (Math.sqrt(2 + 1) - 1) / 2;
con.SQUISH_3D = (Math.sqrt(3 + 1) - 1) / 3;
con.SQUISH_4D = (Math.sqrt(4 + 1) - 1) / 4;
con.STRETCH_2D = (1 / Math.sqrt(2 + 1) - 1) / 2;
con.STRETCH_3D = (1 / Math.sqrt(3 + 1) - 1) / 3;
con.STRETCH_4D = (1 / Math.sqrt(4 + 1) - 1) / 4;
con.base2D = [
[1, 1, 0, 1, 0, 1, 0, 0, 0],
[1, 1, 0, 1, 0, 1, 2, 1, 1]
];
con.base3D = [
[0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1],
[2, 1, 1, 0, 2, 1, 0, 1, 2, 0, 1, 1, 3, 1, 1, 1],
[1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 2, 1, 1, 0, 2, 1, 0, 1, 2, 0, 1, 1]
];
con.base4D = [
[0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1],
[3, 1, 1, 1, 0, 3, 1, 1, 0, 1, 3, 1, 0, 1, 1, 3, 0, 1, 1, 1, 4, 1, 1, 1, 1],
[
1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 2, 1, 1, 0, 0, 2, 1, 0, 1, 0, 2, 1, 0, 0, 1, 2, 0, 1, 1,
0, 2, 0, 1, 0, 1, 2, 0, 0, 1, 1
],
[
3, 1, 1, 1, 0, 3, 1, 1, 0, 1, 3, 1, 0, 1, 1, 3, 0, 1, 1, 1, 2, 1, 1, 0, 0, 2, 1, 0, 1, 0, 2, 1, 0, 0, 1, 2, 0, 1, 1,
0, 2, 0, 1, 0, 1, 2, 0, 0, 1, 1
]
];
con.gradients2D = [5, 2, 2, 5, -5, 2, -2, 5, 5, -2, 2, -5, -5, -2, -2, -5];
con.gradients3D = [
-11, 4, 4, -4, 11, 4, -4, 4, 11,
11, 4, 4, 4, 11, 4, 4, 4, 11,
-11, -4, 4, -4, -11, 4, -4, -4, 11,
11, -4, 4, 4, -11, 4, 4, -4, 11,
-11, 4, -4, -4, 11, -4, -4, 4, -11,
11, 4, -4, 4, 11, -4, 4, 4, -11,
-11, -4, -4, -4, -11, -4, -4, -4, -11,
11, -4, -4, 4, -11, -4, 4, -4, -11
];
con.gradients4D = [
3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3,
-3, 1, 1, 1, -1, 3, 1, 1, -1, 1, 3, 1, -1, 1, 1, 3,
3, -1, 1, 1, 1, -3, 1, 1, 1, -1, 3, 1, 1, -1, 1, 3,
-3, -1, 1, 1, -1, -3, 1, 1, -1, -1, 3, 1, -1, -1, 1, 3,
3, 1, -1, 1, 1, 3, -1, 1, 1, 1, -3, 1, 1, 1, -1, 3,
-3, 1, -1, 1, -1, 3, -1, 1, -1, 1, -3, 1, -1, 1, -1, 3,
3, -1, -1, 1, 1, -3, -1, 1, 1, -1, -3, 1, 1, -1, -1, 3,
-3, -1, -1, 1, -1, -3, -1, 1, -1, -1, -3, 1, -1, -1, -1, 3,
3, 1, 1, -1, 1, 3, 1, -1, 1, 1, 3, -1, 1, 1, 1, -3,
-3, 1, 1, -1, -1, 3, 1, -1, -1, 1, 3, -1, -1, 1, 1, -3,
3, -1, 1, -1, 1, -3, 1, -1, 1, -1, 3, -1, 1, -1, 1, -3,
-3, -1, 1, -1, -1, -3, 1, -1, -1, -1, 3, -1, -1, -1, 1, -3,
3, 1, -1, -1, 1, 3, -1, -1, 1, 1, -3, -1, 1, 1, -1, -3,
-3, 1, -1, -1, -1, 3, -1, -1, -1, 1, -3, -1, -1, 1, -1, -3,
3, -1, -1, -1, 1, -3, -1, -1, 1, -1, -3, -1, 1, -1, -1, -3,
-3, -1, -1, -1, -1, -3, -1, -1, -1, -1, -3, -1, -1, -1, -1, -3
];
con.lookupPairs2D = [0, 1, 1, 0, 4, 1, 17, 0, 20, 2, 21, 2, 22, 5, 23, 5, 26, 4, 39, 3, 42, 4, 43, 3];
con.lookupPairs3D = [
0, 2, 1, 1, 2, 2, 5, 1, 6, 0, 7, 0, 32, 2, 34, 2, 129, 1, 133, 1, 160, 5, 161, 5, 518, 0, 519, 0, 546, 4, 550, 4, 645,
3, 647, 3, 672, 5, 673, 5, 674, 4, 677, 3, 678, 4, 679, 3, 680, 13, 681, 13, 682, 12, 685, 14, 686, 12, 687, 14, 712,
20, 714, 18, 809, 21, 813, 23, 840, 20, 841, 21, 1198, 19, 1199, 22, 1226, 18, 1230, 19, 1325, 23, 1327, 22, 1352, 15,
1353, 17, 1354, 15, 1357, 17, 1358, 16, 1359, 16, 1360, 11, 1361, 10, 1362, 11, 1365, 10, 1366, 9, 1367, 9, 1392, 11,
1394, 11, 1489, 10, 1493, 10, 1520, 8, 1521, 8, 1878, 9, 1879, 9, 1906, 7, 1910, 7, 2005, 6, 2007, 6, 2032, 8, 2033,
8, 2034, 7, 2037, 6, 2038, 7, 2039, 6
];
con.lookupPairs4D = [
0, 3, 1, 2, 2, 3, 5, 2, 6, 1, 7, 1, 8, 3, 9, 2, 10, 3, 13, 2, 16, 3, 18, 3, 22, 1, 23, 1, 24, 3, 26, 3, 33, 2, 37, 2,
38, 1, 39, 1, 41, 2, 45, 2, 54, 1, 55, 1, 56, 0, 57, 0, 58, 0, 59, 0, 60, 0, 61, 0, 62, 0, 63, 0, 256, 3, 258, 3, 264,
3, 266, 3, 272, 3, 274, 3, 280, 3, 282, 3, 2049, 2, 2053, 2, 2057, 2, 2061, 2, 2081, 2, 2085, 2, 2089, 2, 2093, 2,
2304, 9, 2305, 9, 2312, 9, 2313, 9, 16390, 1, 16391, 1, 16406, 1, 16407, 1, 16422, 1, 16423, 1, 16438, 1, 16439, 1,
16642, 8, 16646, 8, 16658, 8, 16662, 8, 18437, 6, 18439, 6, 18469, 6, 18471, 6, 18688, 9, 18689, 9, 18690, 8, 18693,
6, 18694, 8, 18695, 6, 18696, 9, 18697, 9, 18706, 8, 18710, 8, 18725, 6, 18727, 6, 131128, 0, 131129, 0, 131130, 0,
131131, 0, 131132, 0, 131133, 0, 131134, 0, 131135, 0, 131352, 7, 131354, 7, 131384, 7, 131386, 7, 133161, 5, 133165,
5, 133177, 5, 133181, 5, 133376, 9, 133377, 9, 133384, 9, 133385, 9, 133400, 7, 133402, 7, 133417, 5, 133421, 5,
133432, 7, 133433, 5, 133434, 7, 133437, 5, 147510, 4, 147511, 4, 147518, 4, 147519, 4, 147714, 8, 147718, 8, 147730,
8, 147734, 8, 147736, 7, 147738, 7, 147766, 4, 147767, 4, 147768, 7, 147770, 7, 147774, 4, 147775, 4, 149509, 6,
149511, 6, 149541, 6, 149543, 6, 149545, 5, 149549, 5, 149558, 4, 149559, 4, 149561, 5, 149565, 5, 149566, 4, 149567,
4, 149760, 9, 149761, 9, 149762, 8, 149765, 6, 149766, 8, 149767, 6, 149768, 9, 149769, 9, 149778, 8, 149782, 8,
149784, 7, 149786, 7, 149797, 6, 149799, 6, 149801, 5, 149805, 5, 149814, 4, 149815, 4, 149816, 7, 149817, 5, 149818,
7, 149821, 5, 149822, 4, 149823, 4, 149824, 37, 149825, 37, 149826, 36, 149829, 34, 149830, 36, 149831, 34, 149832,
37, 149833, 37, 149842, 36, 149846, 36, 149848, 35, 149850, 35, 149861, 34, 149863, 34, 149865, 33, 149869, 33,
149878, 32, 149879, 32, 149880, 35, 149881, 33, 149882, 35, 149885, 33, 149886, 32, 149887, 32, 150080, 49, 150082,
48, 150088, 49, 150098, 48, 150104, 47, 150106, 47, 151873, 46, 151877, 45, 151881, 46, 151909, 45, 151913, 44,
151917, 44, 152128, 49, 152129, 46, 152136, 49, 152137, 46, 166214, 43, 166215, 42, 166230, 43, 166247, 42, 166262,
41, 166263, 41, 166466, 48, 166470, 43, 166482, 48, 166486, 43, 168261, 45, 168263, 42, 168293, 45, 168295, 42,
168512, 31, 168513, 28, 168514, 31, 168517, 28, 168518, 25, 168519, 25, 280952, 40, 280953, 39, 280954, 40, 280957,
39, 280958, 38, 280959, 38, 281176, 47, 281178, 47, 281208, 40, 281210, 40, 282985, 44, 282989, 44, 283001, 39,
283005, 39, 283208, 30, 283209, 27, 283224, 30, 283241, 27, 283256, 22, 283257, 22, 297334, 41, 297335, 41, 297342,
38, 297343, 38, 297554, 29, 297558, 24, 297562, 29, 297590, 24, 297594, 21, 297598, 21, 299365, 26, 299367, 23,
299373, 26, 299383, 23, 299389, 20, 299391, 20, 299584, 31, 299585, 28, 299586, 31, 299589, 28, 299590, 25, 299591,
25, 299592, 30, 299593, 27, 299602, 29, 299606, 24, 299608, 30, 299610, 29, 299621, 26, 299623, 23, 299625, 27,
299629, 26, 299638, 24, 299639, 23, 299640, 22, 299641, 22, 299642, 21, 299645, 20, 299646, 21, 299647, 20, 299648,
61, 299649, 60, 299650, 61, 299653, 60, 299654, 59, 299655, 59, 299656, 58, 299657, 57, 299666, 55, 299670, 54,
299672, 58, 299674, 55, 299685, 52, 299687, 51, 299689, 57, 299693, 52, 299702, 54, 299703, 51, 299704, 56, 299705,
56, 299706, 53, 299709, 50, 299710, 53, 299711, 50, 299904, 61, 299906, 61, 299912, 58, 299922, 55, 299928, 58,
299930, 55, 301697, 60, 301701, 60, 301705, 57, 301733, 52, 301737, 57, 301741, 52, 301952, 79, 301953, 79, 301960,
76, 301961, 76, 316038, 59, 316039, 59, 316054, 54, 316071, 51, 316086, 54, 316087, 51, 316290, 78, 316294, 78,
316306, 73, 316310, 73, 318085, 77, 318087, 77, 318117, 70, 318119, 70, 318336, 79, 318337, 79, 318338, 78, 318341,
77, 318342, 78, 318343, 77, 430776, 56, 430777, 56, 430778, 53, 430781, 50, 430782, 53, 430783, 50, 431000, 75,
431002, 72, 431032, 75, 431034, 72, 432809, 74, 432813, 69, 432825, 74, 432829, 69, 433032, 76, 433033, 76, 433048,
75, 433065, 74, 433080, 75, 433081, 74, 447158, 71, 447159, 68, 447166, 71, 447167, 68, 447378, 73, 447382, 73,
447386, 72, 447414, 71, 447418, 72, 447422, 71, 449189, 70, 449191, 70, 449197, 69, 449207, 68, 449213, 69, 449215,
68, 449408, 67, 449409, 67, 449410, 66, 449413, 64, 449414, 66, 449415, 64, 449416, 67, 449417, 67, 449426, 66,
449430, 66, 449432, 65, 449434, 65, 449445, 64, 449447, 64, 449449, 63, 449453, 63, 449462, 62, 449463, 62, 449464,
65, 449465, 63, 449466, 65, 449469, 63, 449470, 62, 449471, 62, 449472, 19, 449473, 19, 449474, 18, 449477, 16,
449478, 18, 449479, 16, 449480, 19, 449481, 19, 449490, 18, 449494, 18, 449496, 17, 449498, 17, 449509, 16, 449511,
16, 449513, 15, 449517, 15, 449526, 14, 449527, 14, 449528, 17, 449529, 15, 449530, 17, 449533, 15, 449534, 14,
449535, 14, 449728, 19, 449729, 19, 449730, 18, 449734, 18, 449736, 19, 449737, 19, 449746, 18, 449750, 18, 449752,
17, 449754, 17, 449784, 17, 449786, 17, 451520, 19, 451521, 19, 451525, 16, 451527, 16, 451528, 19, 451529, 19,
451557, 16, 451559, 16, 451561, 15, 451565, 15, 451577, 15, 451581, 15, 451776, 19, 451777, 19, 451784, 19, 451785,
19, 465858, 18, 465861, 16, 465862, 18, 465863, 16, 465874, 18, 465878, 18, 465893, 16, 465895, 16, 465910, 14,
465911, 14, 465918, 14, 465919, 14, 466114, 18, 466118, 18, 466130, 18, 466134, 18, 467909, 16, 467911, 16, 467941,
16, 467943, 16, 468160, 13, 468161, 13, 468162, 13, 468163, 13, 468164, 13, 468165, 13, 468166, 13, 468167, 13,
580568, 17, 580570, 17, 580585, 15, 580589, 15, 580598, 14, 580599, 14, 580600, 17, 580601, 15, 580602, 17, 580605,
15, 580606, 14, 580607, 14, 580824, 17, 580826, 17, 580856, 17, 580858, 17, 582633, 15, 582637, 15, 582649, 15,
582653, 15, 582856, 12, 582857, 12, 582872, 12, 582873, 12, 582888, 12, 582889, 12, 582904, 12, 582905, 12, 596982,
14, 596983, 14, 596990, 14, 596991, 14, 597202, 11, 597206, 11, 597210, 11, 597214, 11, 597234, 11, 597238, 11,
597242, 11, 597246, 11, 599013, 10, 599015, 10, 599021, 10, 599023, 10, 599029, 10, 599031, 10, 599037, 10, 599039,
10, 599232, 13, 599233, 13, 599234, 13, 599235, 13, 599236, 13, 599237, 13, 599238, 13, 599239, 13, 599240, 12,
599241, 12, 599250, 11, 599254, 11, 599256, 12, 599257, 12, 599258, 11, 599262, 11, 599269, 10, 599271, 10, 599272,
12, 599273, 12, 599277, 10, 599279, 10, 599282, 11, 599285, 10, 599286, 11, 599287, 10, 599288, 12, 599289, 12,
599290, 11, 599293, 10, 599294, 11, 599295, 10
];
con.p2D = [0, 0, 1, -1, 0, 0, -1, 1, 0, 2, 1, 1, 1, 2, 2, 0, 1, 2, 0, 2, 1, 0, 0, 0];
con.p3D = [
0, 0, 1, -1, 0, 0, 1, 0, -1, 0, 0, -1, 1, 0, 0, 0, 1, -1, 0, 0, -1, 0, 1, 0, 0, -1, 1, 0, 2, 1, 1, 0, 1, 1, 1, -1, 0,
2, 1, 0, 1, 1, 1, -1, 1, 0, 2, 0, 1, 1, 1, -1, 1, 1, 1, 3, 2, 1, 0, 3, 1, 2, 0, 1, 3, 2, 0, 1, 3, 1, 0, 2, 1, 3, 0, 2,
1, 3, 0, 1, 2, 1, 1, 1, 0, 0, 2, 2, 0, 0, 1, 1, 0, 1, 0, 2, 0, 2, 0, 1, 1, 0, 0, 1, 2, 0, 0, 2, 2, 0, 0, 0, 0, 1, 1,
-1, 1, 2, 0, 0, 0, 0, 1, -1, 1, 1, 2, 0, 0, 0, 0, 1, 1, 1, -1, 2, 3, 1, 1, 1, 2, 0, 0, 2, 2, 3, 1, 1, 1, 2, 2, 0, 0,
2, 3, 1, 1, 1, 2, 0, 2, 0, 2, 1, 1, -1, 1, 2, 0, 0, 2, 2, 1, 1, -1, 1, 2, 2, 0, 0, 2, 1, -1, 1, 1, 2, 0, 0, 2, 2, 1,
-1, 1, 1, 2, 0, 2, 0, 2, 1, 1, 1, -1, 2, 2, 0, 0, 2, 1, 1, 1, -1, 2, 0, 2, 0
];
con.p4D = [
0, 0, 1, -1, 0, 0, 0, 1, 0, -1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 1, 0, 0, 0, 0, 1, -1, 0, 0, 0, 1, 0, -1, 0, 0, -1, 0, 1,
0, 0, 0, -1, 1, 0, 0, 0, 0, 1, -1, 0, 0, -1, 0, 0, 1, 0, 0, -1, 0, 1, 0, 0, 0, -1, 1, 0, 2, 1, 1, 0, 0, 1, 1, 1, -1,
0, 1, 1, 1, 0, -1, 0, 2, 1, 0, 1, 0, 1, 1, -1, 1, 0, 1, 1, 0, 1, -1, 0, 2, 0, 1, 1, 0, 1, -1, 1, 1, 0, 1, 0, 1, 1, -1,
0, 2, 1, 0, 0, 1, 1, 1, -1, 0, 1, 1, 1, 0, -1, 1, 0, 2, 0, 1, 0, 1, 1, -1, 1, 0, 1, 1, 0, 1, -1, 1, 0, 2, 0, 0, 1, 1,
1, -1, 0, 1, 1, 1, 0, -1, 1, 1, 1, 4, 2, 1, 1, 0, 4, 1, 2, 1, 0, 4, 1, 1, 2, 0, 1, 4, 2, 1, 0, 1, 4, 1, 2, 0, 1, 4, 1,
1, 0, 2, 1, 4, 2, 0, 1, 1, 4, 1, 0, 2, 1, 4, 1, 0, 1, 2, 1, 4, 0, 2, 1, 1, 4, 0, 1, 2, 1, 4, 0, 1, 1, 2, 1, 2, 1, 1,
0, 0, 3, 2, 1, 0, 0, 3, 1, 2, 0, 0, 1, 2, 1, 0, 1, 0, 3, 2, 0, 1, 0, 3, 1, 0, 2, 0, 1, 2, 0, 1, 1, 0, 3, 0, 2, 1, 0,
3, 0, 1, 2, 0, 1, 2, 1, 0, 0, 1, 3, 2, 0, 0, 1, 3, 1, 0, 0, 2, 1, 2, 0, 1, 0, 1, 3, 0, 2, 0, 1, 3, 0, 1, 0, 2, 1, 2,
0, 0, 1, 1, 3, 0, 0, 2, 1, 3, 0, 0, 1, 2, 2, 3, 1, 1, 1, 0, 2, 1, 1, 1, -1, 2, 2, 0, 0, 0, 2, 3, 1, 1, 0, 1, 2, 1, 1,
-1, 1, 2, 2, 0, 0, 0, 2, 3, 1, 0, 1, 1, 2, 1, -1, 1, 1, 2, 2, 0, 0, 0, 2, 3, 1, 1, 1, 0, 2, 1, 1, 1, -1, 2, 0, 2, 0,
0, 2, 3, 1, 1, 0, 1, 2, 1, 1, -1, 1, 2, 0, 2, 0, 0, 2, 3, 0, 1, 1, 1, 2, -1, 1, 1, 1, 2, 0, 2, 0, 0, 2, 3, 1, 1, 1, 0,
2, 1, 1, 1, -1, 2, 0, 0, 2, 0, 2, 3, 1, 0, 1, 1, 2, 1, -1, 1, 1, 2, 0, 0, 2, 0, 2, 3, 0, 1, 1, 1, 2, -1, 1, 1, 1, 2,
0, 0, 2, 0, 2, 3, 1, 1, 0, 1, 2, 1, 1, -1, 1, 2, 0, 0, 0, 2, 2, 3, 1, 0, 1, 1, 2, 1, -1, 1, 1, 2, 0, 0, 0, 2, 2, 3, 0,
1, 1, 1, 2, -1, 1, 1, 1, 2, 0, 0, 0, 2, 2, 1, 1, 1, -1, 0, 1, 1, 1, 0, -1, 0, 0, 0, 0, 0, 2, 1, 1, -1, 1, 0, 1, 1, 0,
1, -1, 0, 0, 0, 0, 0, 2, 1, -1, 1, 1, 0, 1, 0, 1, 1, -1, 0, 0, 0, 0, 0, 2, 1, 1, -1, 0, 1, 1, 1, 0, -1, 1, 0, 0, 0, 0,
0, 2, 1, -1, 1, 0, 1, 1, 0, 1, -1, 1, 0, 0, 0, 0, 0, 2, 1, -1, 0, 1, 1, 1, 0, -1, 1, 1, 0, 0, 0, 0, 0, 2, 1, 1, 1, -1,
0, 1, 1, 1, 0, -1, 2, 2, 0, 0, 0, 2, 1, 1, -1, 1, 0, 1, 1, 0, 1, -1, 2, 2, 0, 0, 0, 2, 1, 1, -1, 0, 1, 1, 1, 0, -1, 1,
2, 2, 0, 0, 0, 2, 1, 1, 1, -1, 0, 1, 1, 1, 0, -1, 2, 0, 2, 0, 0, 2, 1, -1, 1, 1, 0, 1, 0, 1, 1, -1, 2, 0, 2, 0, 0, 2,
1, -1, 1, 0, 1, 1, 0, 1, -1, 1, 2, 0, 2, 0, 0, 2, 1, 1, -1, 1, 0, 1, 1, 0, 1, -1, 2, 0, 0, 2, 0, 2, 1, -1, 1, 1, 0, 1,
0, 1, 1, -1, 2, 0, 0, 2, 0, 2, 1, -1, 0, 1, 1, 1, 0, -1, 1, 1, 2, 0, 0, 2, 0, 2, 1, 1, -1, 0, 1, 1, 1, 0, -1, 1, 2, 0,
0, 0, 2, 2, 1, -1, 1, 0, 1, 1, 0, 1, -1, 1, 2, 0, 0, 0, 2, 2, 1, -1, 0, 1, 1, 1, 0, -1, 1, 1, 2, 0, 0, 0, 2, 3, 1, 1,
0, 0, 0, 2, 2, 0, 0, 0, 2, 1, 1, 1, -1, 3, 1, 0, 1, 0, 0, 2, 0, 2, 0, 0, 2, 1, 1, 1, -1, 3, 1, 0, 0, 1, 0, 2, 0, 0, 2,
0, 2, 1, 1, 1, -1, 3, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 2, 1, 1, -1, 1, 3, 1, 0, 1, 0, 0, 2, 0, 2, 0, 0, 2, 1, 1, -1, 1,
3, 1, 0, 0, 0, 1, 2, 0, 0, 0, 2, 2, 1, 1, -1, 1, 3, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 2, 1, -1, 1, 1, 3, 1, 0, 0, 1, 0, 2,
0, 0, 2, 0, 2, 1, -1, 1, 1, 3, 1, 0, 0, 0, 1, 2, 0, 0, 0, 2, 2, 1, -1, 1, 1, 3, 1, 0, 1, 0, 0, 2, 0, 2, 0, 0, 2, -1,
1, 1, 1, 3, 1, 0, 0, 1, 0, 2, 0, 0, 2, 0, 2, -1, 1, 1, 1, 3, 1, 0, 0, 0, 1, 2, 0, 0, 0, 2, 2, -1, 1, 1, 1, 3, 3, 2, 1,
0, 0, 3, 1, 2, 0, 0, 4, 1, 1, 1, 1, 3, 3, 2, 0, 1, 0, 3, 1, 0, 2, 0, 4, 1, 1, 1, 1, 3, 3, 0, 2, 1, 0, 3, 0, 1, 2, 0,
4, 1, 1, 1, 1, 3, 3, 2, 0, 0, 1, 3, 1, 0, 0, 2, 4, 1, 1, 1, 1, 3, 3, 0, 2, 0, 1, 3, 0, 1, 0, 2, 4, 1, 1, 1, 1, 3, 3,
0, 0, 2, 1, 3, 0, 0, 1, 2, 4, 1, 1, 1, 1, 3, 3, 2, 1, 0, 0, 3, 1, 2, 0, 0, 2, 1, 1, 1, -1, 3, 3, 2, 0, 1, 0, 3, 1, 0,
2, 0, 2, 1, 1, 1, -1, 3, 3, 0, 2, 1, 0, 3, 0, 1, 2, 0, 2, 1, 1, 1, -1, 3, 3, 2, 1, 0, 0, 3, 1, 2, 0, 0, 2, 1, 1, -1,
1, 3, 3, 2, 0, 0, 1, 3, 1, 0, 0, 2, 2, 1, 1, -1, 1, 3, 3, 0, 2, 0, 1, 3, 0, 1, 0, 2, 2, 1, 1, -1, 1, 3, 3, 2, 0, 1, 0,
3, 1, 0, 2, 0, 2, 1, -1, 1, 1, 3, 3, 2, 0, 0, 1, 3, 1, 0, 0, 2, 2, 1, -1, 1, 1, 3, 3, 0, 0, 2, 1, 3, 0, 0, 1, 2, 2,
1, -1, 1, 1, 3, 3, 0, 2, 1, 0, 3, 0, 1, 2, 0, 2, -1, 1, 1, 1, 3, 3, 0, 2, 0, 1, 3, 0, 1, 0, 2, 2, -1, 1, 1, 1, 3, 3,
0, 0, 2, 1, 3, 0, 0, 1, 2, 2, -1, 1, 1, 1
];
// helper classes
function shuffleSeed(seed) {
var newSeed = new Uint32Array(1);
newSeed[0] = seed[0] * 1664525 + 1013904223;
return newSeed;
}
function Contribution2(multiplier, xsb, ysb) {
this.dx = -xsb - multiplier * con.SQUISH_2D;
this.dy = -ysb - multiplier * con.SQUISH_2D;
this.xsb = xsb;
this.ysb = ysb;
}
function Contribution3(multiplier, xsb, ysb, zsb) {
this.dx = -xsb - multiplier * con.SQUISH_3D;
this.dy = -ysb - multiplier * con.SQUISH_3D;
this.dz = -zsb - multiplier * con.SQUISH_3D;
this.xsb = xsb;
this.ysb = ysb;
this.zsb = zsb;
}
function Contribution4(multiplier, xsb, ysb, zsb, wsb) {
this.dx = -xsb - multiplier * con.SQUISH_4D;
this.dy = -ysb - multiplier * con.SQUISH_4D;
this.dz = -zsb - multiplier * con.SQUISH_4D;
this.dw = -wsb - multiplier * con.SQUISH_4D;
this.xsb = xsb;
this.ysb = ysb;
this.zsb = zsb;
this.wsb = wsb;
}
// initialize
var contributions2D = [];
for (var i = 0; i < con.p2D.length; i += 4) {
var baseSet = con.base2D[con.p2D[i]];
var previous = null;
var current = null;
for (var k = 0; k < baseSet.length; k += 3) {
current = new Contribution2(baseSet[k], baseSet[k + 1], baseSet[k + 2]);
if (previous === null)
contributions2D[i / 4] = current;
else
previous.next = current;
previous = current;
}
current.next = new Contribution2(con.p2D[i + 1], con.p2D[i + 2], con.p2D[i + 3]);
}
this.lookup2D = [];
for (var i = 0; i < con.lookupPairs2D.length; i += 2) {
this.lookup2D[con.lookupPairs2D[i]] = contributions2D[con.lookupPairs2D[i + 1]];
}
var contributions3D = [];
for (var i = 0; i < con.p3D.length; i += 9) {
var baseSet = con.base3D[con.p3D[i]];
var previous = null;
var current = null;
for (var k = 0; k < baseSet.length; k += 4) {
current = new Contribution3(baseSet[k], baseSet[k + 1], baseSet[k + 2], baseSet[k + 3]);
if (previous === null)
contributions3D[i / 9] = current;
else
previous.next = current;
previous = current;
}
current.next = new Contribution3(con.p3D[i + 1], con.p3D[i + 2], con.p3D[i + 3], con.p3D[i + 4]);
current.next.next = new Contribution3(con.p3D[i + 5], con.p3D[i + 6], con.p3D[i + 7], con.p3D[i + 8]);
}
this.lookup3D = [];
for (var i = 0; i < con.lookupPairs3D.length; i += 2) {
this.lookup3D[con.lookupPairs3D[i]] = contributions3D[con.lookupPairs3D[i + 1]];
}
var contributions4D = [];
for (var i = 0; i < con.p4D.length; i += 16) {
var baseSet = con.base4D[con.p4D[i]];
var previous = null;
var current = null;
for (var k = 0; k < baseSet.length; k += 5) {
current = new Contribution4(baseSet[k], baseSet[k + 1], baseSet[k + 2], baseSet[k + 3], baseSet[k + 4]);
if (previous === null)
contributions4D[i / 16] = current;
else
previous.next = current;
previous = current;
}
current.next = new Contribution4(con.p4D[i + 1], con.p4D[i + 2], con.p4D[i + 3], con.p4D[i + 4], con.p4D[i + 5]);
current.next.next = new Contribution4(con.p4D[i + 6], con.p4D[i + 7], con.p4D[i + 8], con.p4D[i + 9], con.p4D[i + 10]);
current.next.next.next = new Contribution4(con.p4D[i + 11], con.p4D[i + 12], con.p4D[i + 13], con.p4D[i + 14], con.p4D[i + 15]);
}
this.lookup4D = [];
for (var i = 0; i < con.lookupPairs4D.length; i += 2) {
this.lookup4D[con.lookupPairs4D[i]] = contributions4D[con.lookupPairs4D[i + 1]];
}
// end initialize
this.perm = new Uint8Array(256);
this.perm2D = new Uint8Array(256);
this.perm3D = new Uint8Array(256);
this.perm4D = new Uint8Array(256);
var source = new Uint8Array(256);
for (var i = 0; i < 256; i++)
source[i] = i;
var seed = new Uint32Array(1);
seed[0] = clientSeed;
seed = shuffleSeed(shuffleSeed(shuffleSeed(seed)));
for (var i = 255; i >= 0; i--) {
seed = shuffleSeed(seed);
var r = new Uint32Array(1);
r[0] = (seed[0] + 31) % (i + 1);
if (r[0] < 0)
r[0] += (i + 1);
this.perm[i] = source[r[0]];
this.perm2D[i] = this.perm[i] & 0x0E;
this.perm3D[i] = (this.perm[i] % 24) * 3;
this.perm4D[i] = this.perm[i] & 0xFC;
source[r[0]] = source[i];
}
this.simplex1D = function(x) {
return that.simplex2D(x, 1);
}
this.simplex2D = function (x, y) {
var stretchOffset = (x + y) * con.STRETCH_2D;
var _a = [x + stretchOffset, y + stretchOffset], xs = _a[0], ys = _a[1];
var _b = [Math.floor(xs), Math.floor(ys)], xsb = _b[0], ysb = _b[1];
var squishOffset = (xsb + ysb) * con.SQUISH_2D;
var _c = [x - (xsb + squishOffset), y - (ysb + squishOffset)], dx0 = _c[0], dy0 = _c[1];
var _d = [xs - xsb, ys - ysb], xins = _d[0], yins = _d[1];
var inSum = xins + yins;
var hashVals = new Uint32Array(4);
hashVals[0] = xins - yins + 1;
hashVals[1] = inSum;
hashVals[2] = inSum + yins;
hashVals[3] = inSum + xins;
var hash = hashVals[0] | (hashVals[1] << 1) | (hashVals[2] << 2) | (hashVals[3] << 4);
var c = that.lookup2D[hash];
var value = 0.0;
while (typeof c !== 'undefined') {
var _e = [dx0 + c.dx, dy0 + c.dy], dx = _e[0], dy = _e[1];
var attn = 2 - dx * dx - dy * dy;
if (attn > 0) {
var _f = [xsb + c.xsb, ysb + c.ysb], px = _f[0], py = _f[1];
var i = that.perm2D[(that.perm[px & 0xFF] + py) & 0xFF];
var valuePart = con.gradients2D[i] * dx + con.gradients2D[i + 1] * dy;
attn *= attn;
value += attn * attn * valuePart;
}
c = c.next;
}
return value * con.NORM_2D;
};
this.simplex3D = function (x, y, z) {
var stretchOffset = (x + y + z) * con.STRETCH_3D;
var _a = [x + stretchOffset, y + stretchOffset, z + stretchOffset], xs = _a[0], ys = _a[1], zs = _a[2];
var _b = [Math.floor(xs), Math.floor(ys), Math.floor(zs)], xsb = _b[0], ysb = _b[1], zsb = _b[2];
var squishOffset = (xsb + ysb + zsb) * con.SQUISH_3D;
var _c = [x - (xsb + squishOffset), y - (ysb + squishOffset), z - (zsb + squishOffset)], dx0 = _c[0], dy0 = _c[1], dz0 = _c[2];
var _d = [xs - xsb, ys - ysb, zs - zsb], xins = _d[0], yins = _d[1], zins = _d[2];
var inSum = xins + yins + zins;
var hashVals = new Uint32Array(7);
hashVals[0] = yins - zins + 1;
hashVals[1] = xins - yins + 1;
hashVals[2] = xins - zins + 1;
hashVals[3] = inSum;
hashVals[4] = inSum + zins;
hashVals[5] = inSum + yins;
hashVals[6] = inSum + xins;
var hash = hashVals[0] | hashVals[1] << 1 | hashVals[2] << 2 | hashVals[3] << 3 | hashVals[4] << 5 |
hashVals[5] << 7 | hashVals[6] << 9;
var c = that.lookup3D[hash];
var value = 0.0;
while (typeof c !== 'undefined') {
var _e = [dx0 + c.dx, dy0 + c.dy, dz0 + c.dz], dx = _e[0], dy = _e[1], dz = _e[2];
var attn = 2 - dx * dx - dy * dy - dz * dz;
if (attn > 0) {
var _f = [xsb + c.xsb, ysb + c.ysb, zsb + c.zsb], px = _f[0], py = _f[1], pz = _f[2];
var i = that.perm3D[(that.perm[(that.perm[px & 0xFF] + py) & 0xFF] + pz) & 0xFF];
var valuePart = con.gradients3D[i] * dx + con.gradients3D[i + 1] * dy + con.gradients3D[i + 2] * dz;
attn *= attn;
value += attn * attn * valuePart;
}
c = c.next;
}
return value * con.NORM_3D;
};
this.simplex4D = function (x, y, z, w) {
var stretchOffset = (x + y + z + w) * con.STRETCH_4D;
var _a = [x + stretchOffset, y + stretchOffset, z + stretchOffset, w + stretchOffset], xs = _a[0], ys = _a[1], zs = _a[2], ws = _a[3];
var _b = [Math.floor(xs), Math.floor(ys), Math.floor(zs), Math.floor(ws)], xsb = _b[0], ysb = _b[1], zsb = _b[2], wsb = _b[3];
var squishOffset = (xsb + ysb + zsb + wsb) * con.SQUISH_4D;
var dx0 = x - (xsb + squishOffset);
var dy0 = y - (ysb + squishOffset);
var dz0 = z - (zsb + squishOffset);
var dw0 = w - (wsb + squishOffset);
var _c = [xs - xsb, ys - ysb, zs - zsb, ws - wsb], xins = _c[0], yins = _c[1], zins = _c[2], wins = _c[3];
var inSum = xins + yins + zins + wins;
var hashVals = new Uint32Array(11);
hashVals[0] = zins - wins + 1;
hashVals[1] = yins - zins + 1;
hashVals[2] = yins - wins + 1;
hashVals[3] = xins - yins + 1;
hashVals[4] = xins - zins + 1;
hashVals[5] = xins - wins + 1;
hashVals[6] = inSum << 6;
hashVals[7] = inSum + wins;
hashVals[8] = inSum + zins;
hashVals[9] = inSum + yins;
hashVals[10] = inSum + xins;
var hash = hashVals[0] | hashVals[1] << 1 | hashVals[2] << 2 | hashVals[3] << 3 | hashVals[4] << 4 | hashVals[5] << 5 |
hashVals[6] << 6 | hashVals[7] << 8 | hashVals[8] << 11 | hashVals[9] << 14 | hashVals[10] << 17;
var c = that.lookup4D[hash];
var value = 0.0;
while (typeof c !== 'undefined') {
var _d = [dx0 + c.dx, dy0 + c.dy, dz0 + c.dz, dw0 + c.dw], dx = _d[0], dy = _d[1], dz = _d[2], dw = _d[3];
var attn = 2 - dx * dx - dy * dy - dz * dz - dw * dw;
if (attn > 0) {
var _e = [xsb + c.xsb, ysb + c.ysb, zsb + c.zsb, wsb + c.wsb], px = _e[0], py = _e[1], pz = _e[2], pw = _e[3];
var i = that.perm4D[(that.perm[(that.perm[(that.perm[px & 0xFF] + py) & 0xFF] + pz) & 0xFF] + pw) & 0xFF];
var valuePart = con.gradients4D[i] * dx + con.gradients4D[i + 1] * dy + con.gradients4D[i + 2] * dz + con.gradients4D[i + 3] * dw;
attn *= attn;
value += attn * attn * valuePart;
}
c = c.next;
}
return value * con.NORM_4D;
};
}//-13.9
/*--
zim.Point = function(x, y, z, q, r, s, t, u, v, w)
Point
zim class
DESCRIPTION
Stores x, y, z, q, r, s, t, u, v, w properties.
See also createjs.Point for a Point class with more features.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var point = new Point(100, 100);
zog(point.x, point.y); // 100, 100
END EXAMPLE
PARAMETERS
x - (default 0) the x value of the point
y - (default 0) the y value of the point
z - (default 0) the z value of the point - probably not used
q - (default 0) the q value of the point - very probably not used
r - (default 0) the r value of the point - very probably not used
s - (default 0) the s value of the point - very probably not used
t - (default 0) the t value of the point - very probably not used
u - (default 0) the u value of the point - very probably not used
v - (default 0) the v value of the point - very probably not used
w - (default 0) the w value of the point - very probably not used
PROPERTIES
x - the x value of the point
y - the y value of the point
z - the z value of the point - probably not used
q - the q value of the point - very probably not used
r - the r value of the point - very probably not used
s - the s value of the point - very probably not used
t - the t value of the point - very probably not used
u - the u value of the point - very probably not used
v - the v value of the point - very probably not used
w - the w value of the point - very probably not used
--*///+13.45
zim.Point = function(x, y, z, q, r, s, t, u, v, w) {
z_d("13.45");
if (zot(x)) x = 0;
if (zot(y)) y = 0;
if (zot(z)) z = 0;
if (zot(q)) q = 0;
if (zot(r)) r = 0;
if (zot(s)) s = 0;
if (zot(t)) t = 0;
if (zot(u)) u = 0;
if (zot(v)) v = 0;
if (zot(w)) w = 0;
this.x = x;
this.y = y;
this.z = z;
this.q = q;
this.r = r;
this.s = s;
this.t = t;
this.u = u;
this.v = v;
this.w = w;
}//-13.45
/*--
zim.Bezier = function(a, b, c, d)
Bezier
zim class
DESCRIPTION
Creates data for a Cubic Bezier to give x and y at a ratio of the curve
Also gives mx and my for a modified x and y that is more evenly spaced
Thanks Ivo Wetzel - StackExchange
Used internally by zim.getCurvePoint() used by Squiggle, Blob, Beads, and animate() in path
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var a = {x:100, y:100}; // start point
var b = {x:400, y:100}; // control point for start point
var c = {x:100, y:300}; // control point for end point
var d = {x:300, y:300}; // end point
var bezier = new Bezier(a,b,c,d);
new Shape().s(black).mt(a.x,a.y).bt(b.x,b.y, c.x,c.y, d.x,d.y).addTo();
loop(10, function (i) {
// original spacing
// new Circle(5).loc(bezier.x(i/10), bezier.y(i/10));
// modified spacing to be more even
new Circle(5).loc(bezier.mx(i/10), bezier.my(i/10));
});
END EXAMPLE
PARAMETERS
// all parameters are points with x and y properties {x:val, y:val}
a - start point of Bezier curve
b - control point for the start point
c - control point for the end point
d - end point
METHODS
x(r) - the x position of a point at ratio r (0-1) on the curve
y(r) - the y position of a point at ratio r (0-1) on the curve
mx(r) - the evenly-spaced x position of a point at ratio r (0-1) on the curve
my(r) - the evenly-spaced y position of a point at ratio r (0-1) on the curve
PROPERTIES
a, b, c, d - the points passed in - each having x and y properties
--*///+13.47
zim.Bezier = function Bezier(a, b, c, d) {
z_d("13.47");
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.len = 100;
this.arcLengths = new Array(this.len + 1);
this.arcLengths[0] = 0;
var ox = this.x(0), oy = this.y(0), clen = 0;
for(var i = 1; i <= this.len; i += 1) {
var x = this.x(i * 0.01), y = this.y(i * 0.01);
var dx = ox - x, dy = oy - y;
clen += Math.sqrt(dx * dx + dy * dy);
this.arcLengths[i] = clen;
ox = x, oy = y;
}
this.length = clen;
}
zim.Bezier.prototype = {
map: function(u) {
var targetLength = u * this.arcLengths[this.len];
var low = 0, high = this.len, index = 0;
while (low < high) {
index = low + (((high - low) / 2) | 0);
if (this.arcLengths[index] < targetLength) {
low = index + 1;
} else {
high = index;
}
}
if (this.arcLengths[index] > targetLength) {
index--;
}
var lengthBefore = this.arcLengths[index];
if (lengthBefore === targetLength) {
return index / this.len;
} else {
return (index + (targetLength - lengthBefore) / (this.arcLengths[index + 1] - lengthBefore)) / this.len;
}
},
mx: function (u) {
return this.x(this.map(u));
},
my: function (u) {
return this.y(this.map(u));
},
x: function (t) {
return ((1 - t) * (1 - t) * (1 - t)) * this.a.x
+ 3 * ((1 - t) * (1 - t)) * t * this.b.x
+ 3 * (1 - t) * (t * t) * this.c.x
+ (t * t * t) * this.d.x;
},
y: function (t) {
return ((1 - t) * (1 - t) * (1 - t)) * this.a.y
+ 3 * ((1 - t) * (1 - t)) * t * this.b.y
+ 3 * (1 - t) * (t * t) * this.c.y
+ (t * t * t) * this.d.y;
}
};//-13.47
/*--
zim.Boundary = function(x, y, width, height)
Boundary
zim class
DESCRIPTION
Stores the data for a rectangle with x, y, width and height.
Can be used with ZIM drag(), gesture() for boundaries
and the Physics module for world boundary.
NOTE: A createjs.Rectangle or an object {} with x, y, width and height properties can also be used
Boundary was introduced to reduce confusion over having a ZIM Rectangle (Shape) and a CreateJS Rectangle (data)
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
new Circle(100, blue)
.center()
.drag(new Boundary(0,0,stageW,stageH));
// note: drag and gesture used to have rect parameters
// these have now been depreciated and replaced with boundary parameters
// CONTRACT
// the drag() boundary contains the registration point
// note: the gesture() boundary contains the whole shape of the object
// here, we keep the circle inside the stage by contracting the Boundary by the radius
var radius = 100;
new Circle(radius, red)
.center()
.drag(new Boundary(0,0,stageW,stageH).contract(radius));
END EXAMPLE
PARAMETERS
x - the x position of the Boundary
y - the y position of the Boundary
width - the width of the Boundary
height - the height of the Boundary
PROPERTIES
x - the x position of the Boundary
y - the y position of the Boundary
width - the width of the Boundary
height - the height of the Boundary
METHODS
contract(number|x, y, width, height) - number of pixels to make the Boundary smaller
passing in a single number will contract this on all sides
passing in two numbers will contract from horizontal and vertical accordingly
passing in four numbers will contract from the sides accordingly
note: to expand pass in a negative number
returns object for chaining
--*///+13.46
zim.Boundary = function(x, y, width, height) {
z_d("13.46");
if (zot(x) || zot(y) || zot(width) || zot(height)) return;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.contract = function(a,b,c,d) {
if (zot(a)) return this;
if (zot(b)) b = a;
if (zot(c)) {
c = a*2;
} else {
c = c+a;
}
if (zot(d)) {
d = b*2;
} else {
d = d+b;
}
this.x += a;
this.y += b;
this.width -= c;
this.height -= d;
return this;
}
}//-13.46
/*--
zim.GradientColor = function(colors, ratios, x0, y0, x1, y1)
GradientColor
zim class
DESCRIPTION
Creates data for a Linear Gradient that can be used to color ZIM Shapes
like Circle, Rectangle, Triangle, Squiggle, Blob, Flare
and therefore all ZIM component background colors, etc.
Also see ZIM RadialColor and BitmapColor classes
NOTE: the base ZIM Shape class will need gradients applied as usual
NOTE: The chainable methods for linearGradient() and radialGradient() are depricated
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// linear gradient from pink to purple across whole gradient
// with the start at 0,0 and end at 0,500 - so from top to bottom
new Rectangle(1000, 500, new GradientColor([pink,purple], [0,1], 0,0, 0,500)).addTo();
// linear gradient with 30% pink transitioning to green at half way then to 30% pure pink
// along a horizontal path from 0 to 1000 in width
// could also go diagonal for instance 0,0,1000,500
new Rectangle(1000, 500, new GradientColor([pink,green,purple], [.3,.5,.7], 0,0, 1000,0)).addTo()
END EXAMPLE
PARAMETERS
colors - an Array of colors for the gradient, can be more than two
ratios - an Array of 0-1 numbers reprenting the start position of transitions for the colors above
x0 - the x position to start the gradient
y0 - the y position to start the gradient
x1 - the x position to end the gradient
y1 - the y position to end the gradient
PROPERTIES
type - the type of color as a String
** the above parameters are all available as properties
** but will not change objects with their color already set
--*///+13.465
zim.GradientColor = function(colors,ratios, x0,y0, x1,y1) {
z_d("13.465");
this.type = "GradientColor";
this.colors = zot(colors)?["black","white"]:colors;
this.ratios = zot(ratios)?[0,1]:ratios;
this.x0 = zot(x0)?0:x0;
this.y0 = zot(y0)?0:y0;
this.x1 = zot(x1)?0:x1;
this.y1 = zot(y1)?100:y1;
}//-13.465
/*--
zim.RadialColor = function(colors, ratios, x0, y0, r0, x1, y1, r1)
RadialColor
zim class
DESCRIPTION
Creates data for a Radial Gradient that can be used to color ZIM Shapes
like Circle, Rectangle, Triangle, Squiggle, Blob, Flare
and therefore all ZIM component background colors, etc.
Also see ZIM GradientColor and BitmapColor classes
NOTE: the base ZIM Shape class will need gradients applied as usual
NOTE: The chainable methods for linearGradient() and radialGradient() are depricated
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// radial gradient from purple to pink across whole gradient
// with the start at 0,0,200 and end at 0,0,0 - so from radius to center
new Circle(200, new RadialColor([purple,pink], [0,1], 0,0,200, 0,0,0)).center();
// radial gradient from dark to light with alpha reduced
// start fading the light right away to 30% the gradient then use the dark
// move the center of the dark right and up and bigger than radius
// move the center of the light right and up and at 0
// this makes a moon with the dark shade at the bottom left
new Circle(100, new RadialColor(
["rgba(0,0,0,.2)","rgba(255,255,255,.2)"],[0,.3], 50,-30,120, 40,-40,0)
).center()
END EXAMPLE
PARAMETERS
colors - an Array of colors for the gradient, can be more than two
ratios - an Array of 0-1 numbers reprenting the start position of transitions for the colors above
x0 - the x position to start the gradient
y0 - the y position to start the gradient
r0 - the radius at the start of the gradient
x1 - the x position to end the gradient
y1 - the y position to end the gradient
r1 - the radius at the end of the gradient
PROPERTIES
type - the type of color as a String
** the above parameters are all available as properties
** but will not change objects with their color already set
--*///+13.466
zim.RadialColor = function(colors,ratios, x0,y0,r0, x1,y1,r1) {
z_d("13.466");
this.type = "RadialColor";
this.colors = zot(colors)?["black","white"]:colors;
this.ratios = zot(ratios)?[0,1]:ratios;
this.x0 = zot(x0)?0:x0;
this.y0 = zot(y0)?0:y0;
this.r0 = zot(r0)?0:r0;
this.x1 = zot(x1)?0:x1;
this.y1 = zot(y1)?100:y1;
this.r1 = zot(r1)?100:r1;
}//-13.466
/*--
zim.BitmapColor = function(image, repetition, matrix)
BitmapColor
zim class
DESCRIPTION
Creates data for a Bitmap fill from a loaded asset
that can be used to color ZIM Shapes
like Circle, Rectangle, Triangle, Squiggle, Blob, Flare
and therefore all ZIM component background colors, etc.
Also see ZIM GradientColor and RadialColor classes
NOTE: the base ZIM Shape class will need a bitmap fill applied as usual
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var assets = "flecks.jpg";
var path = "assets/";
var frame = new Frame(scaling, width, height, color, outerColor, assets, path);
frame.on("ready", function() {
new Rectangle(frame.width, frame.height, new BitmapColor("flecks.jpg")).addTo();
// or use asset("flecks.png") instead of string "flecks.jpg" - but ZIM will figure it out
stage.update()
}
END EXAMPLE
PARAMETERS
image - a ZIM Bitmap() such as available with asset()
when asset is loaded with ZIM Frame or frame.loadAssets()
also accepts the string name of an asset that would go in asset()
may accept url to html image but image needs to be loaded first
so would recommend usual ZIM asset loading
repetition - (default "repeat") the repeat of the Bitmap fill
also "repeat-x", "repeat-y" or "no-repeat"
matrix - a transformation matrix to apply to the Bitmap
PROPERTIES
type - the type of color as a String
** the above parameters are all available as properties
** but will not change objects with their color already set
--*///+13.467
zim.BitmapColor = function(image, repetition, matrix) {
z_d("13.467");
this.type = "BitmapColor";
if (typeof image == "string" && asset) image = asset(image);
this.image = image.type=="Bitmap"?image.image:image;
this.repetion = repetition;
this.matrix = matrix;
}//-13.467
/*--
zim.Damp = function(startValue, damp)
Damp
zim class
DESCRIPTION
Damping emulates things slowing down due to friction.
The movement heads towards the right value and looks organic.
This is similar if not the same as easing out when tweening.
Create your Damp object outside an interval or Ticker
then inside an interval or ticker call the convert method.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var d = new Damp(parameters);
setInterval(function() {
dampedValue = d.convert(desiredValue);
}, 100);
END EXAMPLE
you would then apply that desired value to a property such as x or y or scale
if you want to do both x and y then you need two Damp objects
and two convert calls (you can do both in one interval or ticker)
EXAMPLE
var circle = new Circle();
circle.center(stage);
var dampX = new Damp(circle.x);
var dampY = new Damp(circle.y);
// start moving once mouse enters stage
// this event will only run once (the last parameter is true)
stage.on("stagemousemove", start, null, true);
function start(e) {
Ticker.add(function() {
circle.x = dampX.convert(e.stageX);
circle.y = dampY.convert(e.stageY);
}, stage);
}
END EXAMPLE
PARAMETERS supports DUO - parameters or single object with properties below
startValue - (default 0) start object at this value and then start damping
damp - (default .1) the damp value with 1 being no damping and 0 being no movement
METHODS
convert(value) - converts a value into a damped value
immediate(value) - immediately goes to value and returns the Damp object
PROPERTIES
damp - can dynamically change the damping (usually just pass it in as a parameter to start)
lastValue - setting this would go immediately to this value (would not normally use)
--*///+14
zim.Damp = function(startValue, damp) {
z_d("14");
var sig = "startValue, damp";
var duo; if (duo = zob(zim.Damp, arguments, sig, this)) return duo;
this.lastValue = (zot(startValue)) ? 0 : startValue;
this.damp = (zot(damp)) ? .1 : damp;
}
zim.Damp.prototype.convert = function(desiredValue) {
return this.lastValue = this.lastValue + (desiredValue - this.lastValue) * this.damp;
}
zim.Damp.prototype.immediate = function(desiredValue) {
this.lastValue = desiredValue;
return this;
}//-14
/*--
zim.Proportion = function(baseMin, baseMax, targetMin, targetMax, factor, targetRound, clamp)
Proportion
zim class
DESCRIPTION
Proportion converts an input value to an output value on a different scale.
(sometimes called a map() function)
For instance, like a slider controlling the scale of an object or sound volume.
Make a Proportion object and then in an interval, ticker or event,
convert the base value to the target value using the convert method.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
frame.loadAssets("mySound.mp3");
frame.on("complete", function() {
var sound = frame.asset("mySound.mp3").play();
var p = new Proportion(0, 10, 0, 1);
var dial = new Dial(); // default range of 0 to 10
dial.currentValue = 10;
dial.on("change", function(){
sound.volume = p.convert(dial.currentValue);
}); // end of dial change
}); // end sound loaded
END EXAMPLE
PARAMETERS supports DUO - parameters or single object with properties below
baseMin - min for the input scale (say x value)
baseMax - max for the input scale (say x value)
targetMin - (default 0) min for the output scale (say volume)
targetMax - (default 1) max for the output scale (say volume)
factor - (default 1) is going the same direction and -1 is going in opposite direction
targetRound - (default false) set to true to round the converted number
clamp - (default true) set to false to let results go outside min and max range
METHODS
convert(input) - will return the output property (for instance, a volume)
NOTE: the object always starts by assuming baseMin as baseValue
just call the convert method right away if you want it to start at a different baseValue
for instance, if your slider went from 100 to 500 and you want to start at half way
make the object and call p.convert(300); on the next line
--*///+15
zim.Proportion = function(baseMin, baseMax, targetMin, targetMax, factor, targetRound, clamp) {
var sig = "baseMin, baseMax, targetMin, targetMax, factor, targetRound, clamp";
var duo; if (duo = zob(zim.Proportion, arguments, sig, this)) return duo;
z_d("15");
// factor - set to 1 for increasing and -1 for decreasing
// round - true to round results to whole number
if (zot(targetMin)) targetMin = 0;
if (zot(targetMax)) targetMax = 1;
if (zot(factor)) factor = 1;
if (zot(targetRound)) targetRound = false;
if (zot(clamp)) clamp = true;
// proportion
var baseAmount;
var proportion;
var targetAmount;
baseAmount = baseMin; // just start at the min otherwise call immediate(baseValue);
this.convert = function(baseAmount) {
if (isNaN(baseAmount) || (baseMax-baseMin==0)) {return;}
if (clamp) {
baseAmount = Math.max(baseAmount, baseMin);
baseAmount = Math.min(baseAmount, baseMax);
}
proportion = (baseAmount - baseMin) / (baseMax - baseMin);
if (factor > 0) {
targetAmount = targetMin + (targetMax-targetMin) * proportion;
} else {
targetAmount = targetMax - (targetMax-targetMin) * proportion;
}
if (targetRound) {targetAmount = Math.round(targetAmount);}
return targetAmount;
}
}//-15
/*--
zim.ProportionDamp = function(baseMin, baseMax, targetMin, targetMax, damp, factor, targetRound, clamp)
ProportionDamp
zim class
DESCRIPTION
ProportionDamp converts an input value to an output value on a different scale with damping.
Works like Proportion Class but with a damping parameter.
Damping needs constant calculating so do not put in mousemove event.
The below example scales the circle based on the mouse height.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var circle = new Circle(50, "red");
circle.center(stage); // center method added in ZIM 4TH
var pd = new ProportionDamp(0, stageH, 0, 5, .2);
Ticker.add(function() {
circle.sca(pd.convert(stage.mouseH)); // scale method added in ZIM 4TH
}, stage);
END EXAMPLE
PARAMETERS supports DUO - parameters or single object with properties below
baseMin - min for the input scale (say x value)
baseMax - max for the input scale (say x value)
targetMin - (default 0) min for the output scale (say volume)
targetMax - (default 1) max for the output scale (say volume)
damp - (default .1) the damp value with 1 being no damping and 0 being no movement
factor (default 1) is going the same direction and -1 is going in opposite direction
targetRound (default false) set to true to round the converted number
METHODS
convert(input) - converts a base value to a target value
immediate(input) - immediately sets the target value (no damping) and returns the ProportionDamp object
dispose() - clears interval
PROPERTIES
damp - can adjust this dynamically (usually just pass it in as a parameter to start)
NOTE: the object always starts by assuming baseMin as baseValue
if you want to start or go to an immediate value without easing then
call the pd.immediate(baseValue) method with your desired baseValue (not targetValue)
--*///+16
zim.ProportionDamp = function(baseMin, baseMax, targetMin, targetMax, damp, factor, targetRound, clamp) {
var sig = "baseMin, baseMax, targetMin, targetMax, damp, factor, targetRound, clamp";
var duo; if (duo = zob(zim.ProportionDamp, arguments, sig, this)) return duo;
z_d("16");
// damp - can be changed via damp get/set method property
// factor - set to 1 for increasing and -1 for decreasing
// round - true to round results to whole number
// zot() is found in danzen.js (the z version of not)
if (zot(targetMin)) targetMin = 0;
if (zot(targetMax)) targetMax = 1;
if (zot(damp)) damp = .1;
if (zot(factor)) factor = 1;
if (zot(targetRound)) targetRound = false;
if (zot(clamp)) clamp = true;
this.damp = damp; // want to expose as a property we can change
var that = this;
// proportion
var baseAmount;
var proportion;
var targetDifference;
var targetAmount;
// damping
var differenceAmount;
var desiredAmount=0;
var lastAmount = 0;
baseAmount = baseMin; // just start at the min otherwise call immediate(baseValue);
lastAmount = targetMin;
var interval = setInterval(calculate, 20);
function calculate() {
if (isNaN(baseAmount) || (baseMax-baseMin==0)) {return;}
if (clamp) {
baseAmount = Math.max(baseAmount, baseMin);
baseAmount = Math.min(baseAmount, baseMax);
}
proportion = (baseAmount - baseMin) / (baseMax - baseMin);
targetDifference = targetMax - targetMin;
if (factor > 0) {
targetAmount = targetMin + targetDifference * proportion;
} else {
targetAmount = targetMax - targetDifference * proportion;
}
desiredAmount = targetAmount;
differenceAmount = desiredAmount - lastAmount;
lastAmount += differenceAmount*that.damp;
}
this.immediate = function(n) {
that.convert(n);
calculate();
lastAmount = targetAmount;
if (targetRound) {lastAmount = Math.round(lastAmount);}
return that;
}
this.convert = function(n) {
baseAmount = n;
if (targetRound) {
return Math.round(lastAmount);
} else {
return lastAmount;
}
}
this.dispose = function(a,b,disposing) {
clearInterval(interval);
return true;
}
}//-16
/*--
zim.Dictionary = function(unique)
Dictionary
zim class
DESCRIPTION
An object that uses objects as keys to give values.
Similar to an object literal with properties except the property names are objects instead of strings.
JavaScript currently does not have a dictionary, but other languages do.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var o = {test:"test"};
var f = function(w) {zog(w)};
var c = new Circle();
var d = new Dictionary();
d.add(o, 1); d.add(f, 2); d.add(c, f);
zog(d.at(o)); // 1
zog(d.at(f)); // 2
d.at(c)("hello"); // hello
d.remove(o); // to clear o
zog(d.length); // 2
END EXAMPLE
EXAMPLE
var d = new Dictionary();
d.add(circle, "one");
d.add(circle, "two");
zog(d.at(circle)); // two - just the latest but "one" is still there
for (var i=0; i -1) return values[i];
return null;
}
this.remove = function(o) {
if (zot(o)) return false;
var i = objects.indexOf(o);
if (i > -1) {
objects.splice(i,1);
values.splice(i,1);
this.length--
return true;
} else {
return false;
}
}
this.clear = function() {
objects = this.objects = []; // store objects and values in synched arrays
values = this.values = [];
this.length = null;
return this;
}
this.dispose = function(a,b,disposing) {
objects = null;
values = null;
this.length = null;
return true;
}
}//-17
/*--
zim.Hierarchy = function(input)
Hierarchy
zim class
DESCRIPTION
A hierarchy is a nested structure for organized data (like XML).
For instance, Hierarchy manages the accordion feature of ZIM List()
where the list can be expanded and collapsed to show nested sections.
HOW IT WORKS
There are two formats that can be used as input.
Each will create a data property in final hierarchy format.
A. The SIMPLE input is an easier format to write but
has a limitation in that identifiers must be strings.
The Hierarchy replaces the identifiers with sequential ids
and stores the original identifiers as an obj property.
B. The COMPLEX input starts off like the final hierarchy data
which has the advantage of storing any type of object in the hierarchy.
The disadvantage is the ids must be hand coded and it is longer.
The Hierarchy will add level, open and opened properties
and create the data property in final hierarchy format.
STRATEGY
The complex format is tricky.
One way to deal with it is to pass in a SIMPLE string version.
Then replace the strings with final objects in the data property.
The Hierarchy class is used internally by ZIM so may not be needed.
However, it will help for custom tree menus, mindmaps, etc.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE - SIMPLE INPUT
// 1. Here is linear input as an array - a boring tree - more like grass!
var simple = [1,2,3,4]; // so we would probably not use Hierarchy for this.
// 2. To hold nested data we use an object literal.
// The properties can hold linear arrays as values
// but if any of the values need to hold more values then use an object literal:
var simple = {
"linear":[1,2,3,4], // an array is okay as all items are leaf nodes (end nodes)
"nested":{ // an object literal is required as one or more items hold other items
"A":[], // this holds nothing (a leaf node) but still needs an empty array
"B":["one", "two", "three"], // this holds a linear list - all leaf nodes
"C":{ // this holds another nested list where at least one item holds more
"LEAF":[],
"LINEAR":[1,2,3,4],
"LEAF":[]
}
}
}
// If EXTRA info is desired this can be handled like so:
// Set the values as a list property of an object and add any extra properties desired
// The extra property does not have to be called extra and there can be multiple extra properties
// Avoid calling the properties list, obj, level, open or opened.
// The extra properties will be added to the complex data objects (see below)
var simple = {
"linear":{list:[1,2,3,4], extra:"val"},
"nested":{list:{ // an object literal is required as one or more items hold other items
"A":[], // this holds nothing (a leaf node) but still needs an empty array
"B":["one", "two", "three"], // this holds a linear list - all leaf nodes
"C":{ // this holds another nested list where at least one item holds more
"LEAF":[],
"LINEAR":[1,2,3,4],
"LEAF":[]
}
}, extra:"val"}
}
// pass the object into the input parameter:
var hierarchy = new Hierarchy(simple);
var data = hierarchy.data;
// data will be the following - note it is a more complex format
// but also a form that could hold any type of data as a value
// note the level matches the indent and all values have an id
data = {
id0:{obj:"linear", level:0, open:false, opened:false, list:{
id1:{obj:1, level:1},
id2:{obj:2, level:1},
id3:{obj:3, level:1},
id4:{obj:4, level:1}
}, extra:"val"},
id5:{obj:"nested", level:0, open:false, opened:false, list:{
id6:{obj:"A", level:1},
id7:{obj:"B", level:1, open:false, opened:false, list:{
id8:{obj:"one", level:2},
id9:{obj:"two", level:2},
id10:{obj:"three", level:2}
}},
id11:{obj:"C", level:1, open:false, opened:false, list:{
id12:{obj:"LEAF", level:2},
id13:{obj:"LINEAR", level:2, open:false, opened:false, list:{
id14:{obj:1, level:3},
id15:{obj:2, level:3},
id16:{obj:3, level:3},
id17:{obj:4, level:3}
}},
id18:{obj:"LEAF", level:2}
}}
}, extra:"val"}
}
END EXAMPLE
EXAMPLE - COMPLEX INPUT
// Here is a sample of passing in the more complex format.
// level, open, opened properties are not required
// they will be added by the Hierarchy.
// Note that there are no arrays in this data format so that each item has an id.
// This could be passed in to the data property of List
// to show an expandable hierarchy of objects rather than strings converted to buttons
var complex = {
id0:{obj:new Rectangle(), list:{
id1:{obj:new Triangle()},
id2:{obj:new Triangle()},
id3:{obj:new Triangle()}
}},
id4:{obj:new Circle(), list:{
id5:{obj:new Button()},
id6:{obj:new Button(), list:{
id7:{obj:new CheckBox()},
id8:{obj:new CheckBox()},
}},
id9:{obj:new Button(), list:{
id10:{obj:new Label("Leaf")},
id11:{obj:new Label("Nest"), list:{
id12:{obj:1},
id13:{obj:2},
id14:{obj:3},
id15:{obj:4},
}},
id16:{obj:new Label("Leaf")}
}}
}}
};
var hierarchy = new Hierarchy(complex);
var list = new List({list:hierarchy.data, align:"center"}).center();
END EXAMPLE
PARAMETERS
input (default null) - a simple formated input - see the examples
this will be turned in to a more complex object literal available as the data property
OR input a complex formated input - similar to the data property output
but only ids, obj and list properties are required.
The main purpose of Hierarchy is to create the complex data object
but passing in a complex format allows objects other than strings to be used.
METHODS
processSimple(input) - enter simple input - returns a Hierarchy data object literal
this is what the Hierarchy does when a simple input is provided to make its data property
the input must be in the simple format as described in the SIMPLE example.
processComplex(input) - enter complex input - returns a Hierarchy data object literal
this is what the Hierarchy does when complex data is provided to make its data property
processComplex will add level, open, and opened properties to the data
otherwise data must be in the same format as the final data property - see COMPLEX example
getLinearList(list) - enter final list from the data format, to get a linear list of top level objects
and all open list objects within according to the open property
getLinearIds(list) - enter final list from the data format, to get a linear list of top level ids
and all open lists ids within according to the open property
getData(id) - find the final data format for a given Hierarchy ID - eg. id0, id12, etc.
pass the data.list to the getLinearList() and getLinearIDs() methods
getNextSibling(id) - gets the id of the next sibling - skipping ids of any children
will find parents next sibling if last child in parent
or undefined if last child in hierarchy
getPrevSibling(id) - gets the id of the previous sibling - skipping ids of any children
will find the parent if first child in parent
or undefined if first child in hierarchy
PROPERTIES
data - a hierarchy formated object literal with ids that hold object literals
ids are in the format of id0, id1, id2, etc. numbered in order of creation (top to bottom)
the object literals have obj, level, open, opened and list properties
leaf nodes (end nodes) will have {} as its list property value
length - read only total length of all nodes
--*///+17.5
zim.Hierarchy = function(input, open) {
z_d("17.5");
var that = this;
if (zot(input)) return;
if (zot(open)) open = false;
var _length;
that.processSimple = function(list) {
var count = 0;
var m = {}
function makeLevel(list, obj, level, last) {
if (list.constructor == {}.constructor) {
var originalList;
if (list.list) { // in extra format
originalList = list;
list = list.list;
}
if (last && originalList) {
zim.loop(originalList, function (k,v) {
if (k=="list") return; // like a for loop continue
last[k] = v;
});
}
zim.loop(list, function (key, val) {
var newList = {};
var current = obj["id"+count] = {obj:key, level:level, open:open, opened:false, list:newList}
count++;
makeLevel(val, newList, level+1, current);
});
} else if (Array.isArray(list)) {
zim.loop(list, function (val) {
var newList = {};
obj["id"+count] = {obj:val}
count++;
});
}
}
makeLevel(input, m, 0);
_length = count;
return m;
}
that.processComplex = function(input) {
var count = 0;
function innerFunction(inp, level) {
zim.loop(inp, function (key, val) {
val.level = level;
if (zot(val.open)) val.open = open;
if (zot(val.opened)) val.opened = false;
if (val.list) innerFunction(val.list, level+1);
count++;
});
}
innerFunction(input, 0);
_length = count;
return input;
}
if (zot(input.id0)) {
that.data = that.processSimple(input);
} else {
that.data = that.processComplex(input);
}
that.getLinearList = function(data) {
if (zot(data)) data = that.data;
return getLinear(data)[0];
}
that.getLinearIDs = function(data) {
if (zot(data)) data = that.data;
return getLinear(data)[1];
}
function getLinear(data) {
var linear = [];
var ids = [];
function getLevel(data, level) {
zim.loop(data, function (item, list) {
linear.push(list.obj);
ids.push(item);
if (list.open) getLevel(list.list, level+1);
})
}
getLevel(data, 0);
return [linear, ids];
}
that.getData = function(id) {
// recursively find the data for id
var answer;
function find(obj) {
zim.loop(obj, function (key, val) {
if (key == id) {
answer = val;
return answer;
}
find(val.list);
});
}
find(that.data);
return answer;
}
that.getNextSibling = function(id) {
var current;
var answer;
function find(obj) {
zim.loop(obj, function (key, val) {
if (!answer && current) {
answer = key;
return answer;
}
if (key == id) {
current = val;
} else {
find(val.list);
}
});
}
find(that.data);
return answer;
}
that.getPrevSibling = function(id) {
var lasts = [];
function find(obj, lev) {
zim.loop(obj, function (key, val) {
if (key == id) {
return lasts[lev] || lasts[lev-1];
} else {
lasts[lev] = key;
find(val.list, lev+1);
}
});
}
find(that.data, 0);
return answer;
}
Object.defineProperty(that, 'length', {
get: function() {
return _length;
},
set: function(value) {
if (zon) zogy("Hierarchy() - length is read only")
}
});
}//-17.5
/*--
zim.Pick = function(choices)
Pick
zim class
HISTORY
Pick was originally zik() and ZIM VEE (introduced in ZIM 5) throughout the ZIM documentation
It was so handy that a general (non ZIM centric) name has been given to a class
that can be used by other libraries and languages.
See https://github.com/danzen/Pick for the complete general code and description
DESCRIPTION
Pick() provides a system to handle dynamic parameters.
It does so by providing formats for options and a choose() method to pick from the options.
For example, a particle emitter has an obj parameter to receive what type of particle to emit.
If a particle were randomly chosen from a rectangle, circle or triangle and passed into obj
then the emitter would only emit the randomly chosen particle - say, a bunch of triangles.
What is desired is that the emitter emit rectangles, circles and triangles randomly.
Pick() provides a way to pass in all three shapes and have the emitter choose each time it emits.
FORMATS
The Pick() formats handle:
1. a random selection: ["blue", "green", "yellow"] - array format
2. a random range: {min:10, max:30} - range object format
3. a series: series(10,20,30) - series format also Pick.series()
4. a function result: function(){return new Date().minutes} - function format
5. a normal value: 7 or "hello" - single-value format
6. a noPick object: {noPick:["real", "array"]} - escape format
7. a combination: [{min:10, max:20}, 30, 40] - combination format (recursive)
NOTE: the range format gets passed to ZIM rand() directly so see docs there
there are also integer and negative parameters both defaulting to false
PICK LITERAL
Formats are passed in to a Pick() object and the Pick object can be passed to a class or function parameter
In ZIM, the formats may be passed directly into the class or function parameter (as a Pick literal)
new Circle(new Pick([10,20]), red); // Pick()
new Circle([10,20], red); // Pick Literal
** The literal can run into conflicts such as for a ZIM corner parameter which accepts an array []
This would be avoided with a system always using Pick() and never the literal.
But... ZIM started off without the formalized Pick - and the literal is shorter ;-)
NOTE: Pick is used internally by by zim.interval, zim.animate, zim.Emitter, zim.Pen, etc.
as well as ZIM Shape basic parameters handy for cloning with Tile, Emitter, etc.
EXAMPLE
var loopCount = new Pick([1,2,3]);
var choice = Pick.choose(loopCount); // 1, 2, or 3
var loopCount = [1,2,3]; // Pick literal
var choice = Pick.choose(loopCount); // 1, 2, or 3
var choice = Pick.choose([1,2,3]); // 1, 2, or 3
var rotation = {min:10, max:20, integer:false, negative:true};
// an example of a Range object - this will give values between -20 and -10 or 10 and 20
// rotation now holds an object as to how to pick its value
// this can be passed into a zim.Emitter() for instance
// which will make multiple copies and rotate them based on Pick.choose()
// or this can be passed into an animation object
// and then into zim.Emitter() for the animate parameter
var emitter = new zim.Emitter({
obj:new zim.Rectangle(),
random:{rotation:rotation} // the emitter will use Pick.choose() to pick a rotation for each particle
});
function age() {
// assuming user.age is some input value that exists
if (user.age >= 18) return ["a", "b", ["c","d"]];
else return ["e", "f"];
}
// below will be a, b, c or d if user is 18+ with a and b having more of a chance
// or e or f if not over 18
var show = Pick.choose(age);
// below we randomize the tile colors in the first example
// and make them in color order for the second example
new Tile(new Rectangle(10,10,["blue", "red"]), 10, 10); would randomize colors
new Tile(new Rectangle(10,10,series("blue", "red")), 10, 10); would alternate colors
// here we pass an array through without processing the array:
Pick.choose({noPick:[1,2,3,4,5]}); // result is [1,2,3,4,5]
// a range between one and three seconds - repeating after 3 choices
var pick = new Pick({min:1000, max:3000}).num(3);
interval(pick, function () {console.log("calling");}); // eg. 2.5s, 2.7s, 1.2s, 2.5s, 2.7s, 1.2s, etc.
END EXAMPLE
PARAMETERS
choices - any of the ZIM Pick formats:
1. an array of choices to choose from randomly
2. a range object with min and max (integer and negative) properties
3. a zim.series() or Pick.series() to pick objects in order
4. a function that returns a result
5. a single not one of the above that passes through
6. an escape object with a noPick property
7. any combination of the above to pick recursively
METHODS
num(number) - a chainable method to limit the number of options until Pick.choose() will repeat like a series
loop(number, call(value, index, total)) - a way to loop through options
number is the number of times to loop
call is a callback function that gets called each loop
the callback will recieve a value (the choice), the index of the loop and the total (the number parameter)
inside the function a return is like a continue and a return of any value is like a break in traditional for loops.
STATIC METHODS
Pick.choose(Pick Object or Pick Literal) - gets a value from the Pick object or Pick Literal
so chooses from a random array, or range, or gets the next in the series, etc.
Pick.rand(a, b, integer, negative) - gets a random number - same as zim.rand()
a - the first Number for the range
if a and b are not provided, rand() acts like Math.random()
if parameter b is not provided, rand will use range 0 to and including a
b - (default 0) second Number for the range
it does not matter if a>b or a= steps) {
window.scrollTo(zim["scroll"+perpend](), num);
clearInterval(scrollInterval);
}
}, interval);
}
return num;
}//-20
/*--
zim.windowWidth = function()
windowWidth
zim function
DESCRIPTION
Returns the width of a window.
(window.clientWidth or window.innerWidth)
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
if (windowWidth() < 500) zss("related").display = "none";
END EXAMPLE
RETURNS a Number
--*///+21
zim.windowWidth = function() {
z_d("21");
var w = isNaN(window.innerWidth) ? window.clientWidth : window.innerWidth;
var h = isNaN(window.innerHeight) ? window.clientHeight : window.innerHeight;
if (zim.mobile() && !zot(window.orientation)) {
if ((w > h && Math.abs(window.orientation) != 90) || h > w && Math.abs(window.orientation) == 90) {
var oldW = w;
w = h;
h = oldW;
}
}
// 6. part of TEN PATCH
// pay attention to swapRotation from Frame
return (typeof zimDefaultFrame != "undefined" && zimDefaultFrame.swapRotation)?h:w;
}//-21
/*--
zim.windowHeight = function()
windowHeight
zim function
DESCRIPTION
Returns the height of a window.
(window.clientHeight or window.innerHeight)
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
if (windowHeight() > 1000) zgo("big.html");
END EXAMPLE
RETURNS a Number
--*///+22
zim.windowHeight = function() {
z_d("22");
var w = isNaN(window.innerWidth) ? window.clientWidth : window.innerWidth;
var h = isNaN(window.innerHeight) ? window.clientHeight : window.innerHeight;
if (zim.mobile() && !zot(window.orientation)) {
if ((w > h && Math.abs(window.orientation) != 90) || h > w && Math.abs(window.orientation) == 90) {
var oldW = w;
w = h;
h = oldW;
}
}
// 7. part of TEN PATCH
// pay attention to swapRotation from Frame
return (typeof zimDefaultFrame != "undefined" && zimDefaultFrame.swapRotation)?w:h;
}//-22
/*--
zim.getQueryString = function(string)
getQueryString
zim function
DESCRIPTION
Turns the HTML query string into a object.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// currentHTML page myPage.html?party=true&toys=many
var details = getQueryString();
zog(details.party); // "true"
zog(details.toys); // "many"
loop(details, function(key, val, i) {
zog(key, val, i);
});
// outputs:
// party true 0
// toys many 1
END EXAMPLE
EXAMPLE
// an array of values is created if a query string has multiple properties with the same name:
var collection = getQueryString("type=dog&age=10&age=20&age=30");
zog(collection.age); // [10,20,30]
END EXAMPLE
PARAMETERS
string - (default null) null will get string from end of HTML page after ?
set the key value pairs (without question mark) to parse a custom string
eg. party=true&toys=many
RETURNS an object literal with properties matching the keys and values matching the values (or undefined if no query string)
--*///+22.5
zim.getQueryString = function(s) {
z_d("22.5");
if (zot(s)) s = location.search.replace("?","");
if (s == "") return;
var vars = s.split("&");
var obj = {};
for (var i=0; i= 4.3.0 requires createjs namespace to be loaded (import createjs before zim)");} return zim;}
//////////////// ZIM DISPLAY //////////////
// Zim Display (formerly Zim Build) adds common display classes for multies (interactive media)
// classes in this module require createjs namespace to exist and in particular easel.js
// available at http://createjs.com
/*--
zim.Coordinates = function(canvasID)
Helper functions for localToGlobal, globalToLocal and localToLocal
--*///+50.43
zim.coordinatesCheck = false;
zim.localToGlobal = function localToGlobal(x,y,scope,func) {
if (!zim.coordinatesCheck) {z_d("50.43"); zim.coordinatesCheck=true;}
if (x==null || y==null) return;
var point = func.call(scope,x,y);
var stage = scope.stage;
if (typeof zimDefaultFrame == "undefined") {
if (!stage) return point;
zimDefaultFrame = {stage:stage, canvas:stage.canvas};
}
point.x /= zim.scaX;
point.y /= zim.scaY;
return point;
}
zim.globalToLocal = function globalToLocal(x,y,scope,func) {
if (!zim.coordinatesCheck) {z_d("50.43"); zim.coordinatesCheck=true;}
if (x==null || y==null) return;
var stage = scope.stage;
if (typeof zimDefaultFrame == "undefined") {
if (!stage) return func.call(scope,x,y);
zimDefaultFrame = {stage:stage, canvas:stage.canvas};
}
x *= zim.scaX;
y *= zim.scaY;
var point = func.call(scope,x,y);
return point;
}
zim.localToLocal = function localToLocal(x,y,target,scope) {
if (!zim.coordinatesCheck) {z_d("50.43"); zim.coordinatesCheck=true;}
if (x==null || y==null || target==null) return;
var point = scope.localToGlobal(x,y);
var stage = scope.stage;
if (typeof zimDefaultFrame == "undefined") {
if (!stage) return target.globalToLocal(point.x, point.y);
zimDefaultFrame = {stage:stage, canvas:stage.canvas};
}
if (!stage) stage = zimDefaultFrame.stage;
if (target == stage) return point;
if (point) return target.globalToLocal(point.x, point.y);
}
//-50.43
/*--
zim.Stage = function(canvasID)
Stage
zim class - extends a createjs.Stage which extends a createjs.Container
DESCRIPTION
An extension of a createjs.Stage that includes read only type, width and height properties, loop and hitTestGrid methods.
When using zim.Frame, there should be no reason to make a zim.Stage.
This was put in place to match the ZIM TypeScript typings for stage width and height.
Also see https://www.createjs.com/docs/easeljs/classes/Stage.html
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var stage = new Stage("canvasID");
END EXAMPLE
PARAMETERS
canvasID - (default null) string ID for canvas tag
METHODS
loop(call, reverse, step, start, end) - see the ZIM Display Methods loop() for details
see the ZIM Display Methods loop() for details
hitTestGrid(width, height, cols, rows, x, y, offsetX, offsetY, spacingX, spacingY, local, type)
see the ZIM Display Methods hitTestGrid() for details
See the CreateJS Easel Docs for Stage methods, such as:
clear, update, toDataURL
And all the Container methods such as:
on, off, setBounds, getBounds, globalToLocal, etc.
PROPERTIES
frame - if made with ZIM Frame then frame points to the frame that made the stage
type - holds the class name as a String
width - read only width set by ZIM Frame
height - read only height set by ZIM Frame
ALSO: See the CreateJS Easel Docs for Stage properties, such as:
autoClear, canvas, nextStage, etc.
and all the Container properties, such as:
children, mouseChildren, filters, cacheCanvas, etc.
Note: also makes a partial zimDefaultFrame allowing circle.center() to work
but will be overwritten if an actual Frame is made
EVENTS
See the CreateJS Easel Docs for Stage events, such as:
mouseenter, mouseleave, stagemousedown, stagemousemove, stagemouseup, drawstart, drawend, etc.
and all the Container events, such as:
click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+50.44
zim.Stage = function(canvasID) {
z_d("50.44");
if (zot(canvasID)) return;
var tag = canvasID.tagName=="CANVAS"?canvasID:zid(canvasID);
if (zot(tag)) return;
this.cjsStage_constructor(canvasID);
this.setBounds(0,0,tag.width,tag.height);
this.type = "Stage";
if (typeof zimDefaultFrame == 'undefined') zimDefaultFrame = {stage:this};
this.cache = function(a,b,c,d,scale,options) {
if (zot(c)) {
if (zot(a)) {
var bounds = this.getBounds();
if (!zot(bounds)) {
var added = this.borderWidth > 0 ? this.borderWidth/2 : 0;
a = bounds.x-added;
b = bounds.y-added;
c = bounds.width+added*2;
d = bounds.height+added*2;
}
} else {
c = a;
d = b;
a = 0;
b = 0;
}
}
this.cjsStage_cache(a,b,c,d,scale,options);
return this;
}
this.loop = function(call, reverse, step, start, end) {
return zim.loop(this, call, reverse, step, start, end);
}
this.hitTestGrid = function(width, height, cols, rows, x, y, offsetX, offsetY, spacingX, spacingY, local, type) {
return zim.hitTestGrid(this, width, height, cols, rows, x, y, offsetX, offsetY, spacingX, spacingY, local, type);
}
if (createjs && !createjs.stageTransformable && (zimDefaultFrame.retina || typeof exportRoot != "undefined")) {
Object.defineProperty(this, 'scale', {
get: function() {
return this.cjsStage_scale;
},
set: function(value) {
this.cjsStage_scaleX = value;
this.cjsStage_scaleY = value;
zim.scaX = createjs.stageTransformable ? 1 : value;
zim.scaY = createjs.stageTransformable ? 1 : value;
}
});
Object.defineProperty(this, 'scaleX', {
get: function() {
return this.cjsStage_scaleX;
},
set: function(value) {
this.cjsStage_scaleX = value;
zim.scaX = createjs.stageTransformable ? 1 : value;
}
});
Object.defineProperty(this, 'scaleY', {
get: function() {
return this.cjsStage_scaleY;
},
set: function(value) {
this.cjsStage_scaleY = value;
zim.scaY = createjs.stageTransformable ? 1 : value;
}
});
this.localToGlobal = function(x,y) {
return zim.localToGlobal(x,y,this,this.cjsStage_localToGlobal);
}
this.globalToLocal = function(x,y) {
return zim.globalToLocal(x,y,this,this.cjsStage_globalToLocal);
}
this.localToLocal = function(x,y,target) {
return zim.localToLocal(x,y,target,this);
}
}
}
zim.extend(zim.Stage, createjs.Stage, ["cache","localToLocal","localToGlobal","globalToLocal"], "cjsStage", false);
//-50.44
/*--
zim.StageGL = function(canvasID, options)
StageGL
zim class - extends a zim.Stage which extends a createjs.Stage
DESCRIPTION
An extension of a zim.Stage for WebGL support
See ZIM Stage and https://www.createjs.com/docs/easeljs/classes/StageGL.html
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var stage = new StageGL("canvasID", {preserveBuffer:true, antialias:true});
END EXAMPLE
PARAMETERS
canvasID - (default null) string ID for canvas tag
options - (default null) an object literal with the following properties
FROM https://www.createjs.com/docs/easeljs/classes/StageGL.html
preserveBuffer (default false)
If true, the canvas is NOT auto-cleared by WebGL (the spec discourages setting this to true). This is useful if you want persistent draw effects.
antialias (default false)
Specifies whether or not the browser's WebGL implementation should try to perform anti-aliasing. This will also enable linear pixel sampling on power-of-two textures (smoother images).
transparent (default false)
If true, the canvas is transparent. This is very expensive, and should be used with caution.
premultiply (default false)
Alters color handling. If true, this assumes the shader must account for pre-multiplied alpha. This can help avoid visual halo effects with some assets, but may also cause problems with other assets.
autoPurge (default 1200)
How often the system should automatically dump unused textures with purgeTextures(autoPurge) every autoPurge/2 draws. See purgeTextures for more information.
METHODS
loop(call, reverse, step, start, end) - see the ZIM Display Methods loop() for details
see the ZIM Display Methods loop() for details
hitTestGrid(width, height, cols, rows, x, y, offsetX, offsetY, spacingX, spacingY, local, type)
see the ZIM Display Methods hitTestGrid() for details
See the CreateJS Easel Docs for StageGL methods:
https://www.createjs.com/docs/easeljs/classes/StageGL.html
PROPERTIES
frame - if made with ZIM Frame then frame points to the frame that made the stage
type - holds the class name as a String
width - read only width set by ZIM Frame
height - read only height set by ZIM Frame
See the CreateJS Easel Docs for Stage properties:
https://www.createjs.com/docs/easeljs/classes/StageGL.html
Note: also makes a partial zimDefaultFrame allowing circle.center() to work
but will be overwritten if an actual Frame is made
EVENTS
See the CreateJS Easel Docs for StageGL events, such as:
mouseenter, mouseleave, stagemousedown, stagemousemove, stagemouseup, drawstart, drawend, etc.
and all the Container events, such as:
click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+50.45
zim.StageGL = function(canvasID, options) {
z_d("50.45");
if (zot(canvasID)) return;
var tag = canvasID.tagName=="CANVAS"?canvasID:zid(canvasID);
if (zot(tag)) return;
this.cjsStageGL_constructor(canvasID, options);
this.setBounds(0,0,tag.width,tag.height);
this.type = "StageGL";
if (typeof zimDefaultFrame == 'undefined') zimDefaultFrame = {stage:this};
this.cache = function(a,b,c,d,scale,options) {
if (zot(c)) {
if (zot(a)) {
var bounds = this.getBounds();
if (!zot(bounds)) {
var added = this.borderWidth > 0 ? this.borderWidth/2 : 0;
a = bounds.x-added;
b = bounds.y-added;
c = bounds.width+added*2;
d = bounds.height+added*2;
}
} else {
c = a;
d = b;
a = 0;
b = 0;
}
}
this.cjsStageGL_cache(a,b,c,d,scale,options);
return this;
}
this.loop = function(call, reverse, step, start, end) {
return zim.loop(this, call, reverse, step, start, end);
}
this.hitTestGrid = function(width, height, cols, rows, x, y, offsetX, offsetY, spacingX, spacingY, local, type) {
return zim.hitTestGrid(this, width, height, cols, rows, x, y, offsetX, offsetY, spacingX, spacingY, local, type);
}
var frame = zimDefaultFrame || 1;
if (createjs && !createjs.stageTransformable && (zimDefaultFrame.retina || typeof exportRoot != "undefined")) {
Object.defineProperty(this, 'scale', {
get: function() {
return this.cjsStage_scale;
},
set: function(value) {
this.cjsStage_scaleX = value;
this.cjsStage_scaleY = value;
zim.scaX = createjs.stageTransformable ? 1 : value;
zim.scaY = createjs.stageTransformable ? 1 : value;
}
});
Object.defineProperty(this, 'scaleX', {
get: function() {
return this.cjsStage_scaleX;
},
set: function(value) {
this.cjsStage_scaleX = value;
zim.scaX = createjs.stageTransformable ? 1 : value;
}
});
Object.defineProperty(this, 'scaleY', {
get: function() {
return this.cjsStage_scaleY;
},
set: function(value) {
this.cjsStage_scaleY = value;
zim.scaY = createjs.stageTransformable ? 1 : value;
}
});
this.localToGlobal = function(x,y) {
return zim.localToGlobal(x,y,this,this.cjsStageGL_localToGlobal);
}
this.globalToLocal = function(x,y) {
return zim.globalToLocal(x,y,this,this.cjsStageGL_globalToLocal);
}
this.localToLocal = function(x,y,target) {
return zim.localToLocal(x,y,target,this);
}
}
}
zim.extend(zim.StageGL, createjs.StageGL, ["cache","localToLocal","localToGlobal","globalToLocal"], "cjsStageGL", false);
//-50.45
/*--
zim.Container = function(a, b, c, d, style, group, inherit)
Container
zim class - extends a createjs.Container
DESCRIPTION
A Container object is used to hold other display objects or other containers.
You can then move or scale the container and all objects inside will move or scale.
You can apply an event on a container and use the target property of the event object
to access the object in the container that caused the event
or use the currentTarget property of the event object to access the container itself.
Containers do not have bounds unless some items in the container have bounds -
at which point the bounds are the combination of the bounds of the objects with bounds.
You can manually set the bounds with setBounds(x,y,w,h) - read the CreateJS docs.
Or pass in width and height, or boundsX, boundsY, width, height to have Container set bounds
Manually set bounds will not update automatically unless you setBounds(null).
NOTE: All the ZIM shapes and components extend the Container.
This means all shapes and components inherit the methods and properties below
and indeed, the Container inherits all the createjs.Container methods and properties.
See the CreateJS documentation for x, y, alpha, rotation, on(), addChild(), etc.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var container = new Container();
stage.addChild(container);
container.x = 100; container.y = 100;
// demonstration of adding drag() to a Container
var rect = new Rectangle(100, 100, "blue");
container.addChild(rect); // add rectangle to container
var circle = new Circle(40, "red");
circle.center(container) // add the circle to the container and center
container.drag(); // will drag either the rectangle or the circle
container.drag({currentTarget:true}); // will drag both the rectangle and the circle
// below will reduce the alpha of the object in the container that was clicked (target)
container.on("click" function(e) {e.target.alpha = .5; stage.update();})
// below will reduce the alpha of all the objects in the container (currentTarget)
container.on("click" function(e) {e.currentTarget.alpha = .5; stage.update();})
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
** Container supports three different sets of parameters as follows:
a - (default null) - width and height equal to parameter a (x and y will be 0)
a, b - (default null) - the width and height (x and y will be 0)
a, b, c, d - (default null) - the x, y, width and height of the bounds
if parameter a is not set, then the Container will take bounds that grow with its content
the bounds of the Container can be set at any time with setBounds(a, b, c, d)
if the bounds are set, then the Container bounds will not change as content is added
the bounds can be removed with setBounds(null) and the Container will get auto bounds
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var circle = new Circle();
circle.center(stage); // add circle to stage and center
circle.drag();
// alternatively, we can still use the traditional ZIM functions:
center(circle, stage);
drag(circle);
// ZIM DUO works the same way as before - eg.
circle.drag({slide:true});
END EXAMPLE
METHODS
* This class has all the DISPLAY METHODS introduced in ZIM 4TH
* the methods are available to all ZIM Display objects that extend a ZIM Container
* such as ZIM Rectangle, Circle, Triangle, BLob
* as well as all components like: Label, Button, Slider, Dial, Tab, Pane, etc.
* as well as the ZIM display wrappers: Container, Shape, Sprite, MovieClip and Bitmap
cache(width||x, height||y, null||width, null||height, scale, options, margin) - overrides CreateJS cache() and returns object for chaining
If you do not provide the first four parameters, then the cache dimensions will be set to the bounds of the object
width||x - (default getBounds().x) the width of the chache - or the x if first four parameters are provided
height||y - (default getBounds().y) the height of the chache - or the y if first four parameters are provided
width - (default getBounds().width) the width of the chache - or null if first two parameters are provided
height - (default getBounds().height) the height of the chache - or null if first two parameters are provided
scale - (default 1) set to 2 to cache with twice the fidelity if later scaling up
options - (default null) additional parameters for cache logic - see CreateJS somewhere for details
margin - (default 0) add or subtract a margin from the bounds
eg. margin:10 will make the cache size 10 pixels more on all sides
this can be handy when caching objects with borders - that go half outside the natural bounds
setBounds(width||x, height||y, null||width, null||height) - overrides CreateJS setBounds() and returns object for chaining
If you do not provide the any parameters, then the bounds will be reset to the calculated bounds
width||x - (default null) the width of the bounds - or the x if four parameters are provided
height||y - (default width) the height of the bounds - or the y if four parameters are provided
width - (default null) the width of the bounds - or null if only the first two parameters are provided
height - (default null) the height of the bounds - or null if only the first two parameters are provided
childrenToBitmap() - turns content to a Bitmap and adds bitmap to container - removing all other children
specialColor(colorCommand, colorObject) - used internally by ZIM Shapes
to set GradientColor, RadialColor and BitmapColor on a fill or stroke color command
hasProp(property as String) - returns true if property exists on object else returns false
clone(exact) - clones the container, its properties and all its children
exact (default false) ZIM VEE (Pick) values are active in clones unless exact is set to true
For instance, if a Container holds a new Circle(20,[blue,green])
then its clone might be blue or green
If exact is set to true then the clone will be whatever color was picked for the original circle
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
** bounds must be set first (or width and height parameters set) for these to work
** setting these adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
depth - for ZIM VR - the depth used to shift left and right channel and for parallax in VR - also see dep() ZIM Display method
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scale, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+50.5
zim.containerCheck = false;
zim.Container = function(a, b, c, d, style, group, inherit) {
var sig = "a, b, c, d, style, group, inherit";
var duo; if (duo = zob(zim.Container, arguments, sig, this)) return duo;
if (!zim.containerCheck) {z_d("50.5"); zim.containerCheck=true;}
this.cjsContainer_constructor();
this.type = "Container";
this.group = group;
var that = this;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(a)) a = DS.a!=null?DS.a:null;
if (zot(b)) b = DS.b!=null?DS.b:null;
if (zot(c)) c = DS.c!=null?DS.c:null;
if (zot(d)) d = DS.d!=null?DS.d:null;
var n = normalizeBounds(a, b, c, d);
function normalizeBounds(a, b, c, d) {
var bounds = [];
if (zot(a)) {
bounds = [a,b,c,d];
} else if (!zot(c)) {
bounds[0] = a;
bounds[2] = c;
bounds[1] = b;
bounds[3] = d;
} else {
bounds[0] = 0;
bounds[2] = a;
bounds[1] = 0;
bounds[3] = b;
}
if (zot(bounds[3])) bounds[3] = bounds[2];
return bounds;
}
if (!zot(a)) this.setBounds(n[0],n[1],n[2],n[3]); // es6 to fix
this.cache = function(a,b,c,d,scale,options,margin) {
var sig = "a,b,c,d,scale,options,margin";
var duo; if (duo = zob(that.cache, arguments, sig)) return duo;
var bounds = that.getBounds();
if (zot(c)) {
if (zot(a)) {
if (!zot(bounds)) {
var added = that.borderWidth > 0 ? that.borderWidth/2 : 0;
a = bounds.x-added;
b = bounds.y-added;
c = bounds.width+added*2;
d = bounds.height+added*2;
}
} else {
c = a;
d = b;
a = 0;
b = 0;
}
}
if (that.type == "Triangle") {
a-=that.borderWidth?that.borderWidth:0;
c+=that.borderWidth?that.borderWidth*2:0;
b-=that.borderWidth?that.borderWidth:0;
d+=that.borderWidth?that.borderWidth*2:0;
}
if (zot(margin)) margin = 0;
that.cjsContainer_cache(a-margin,b-margin,c+margin*2,d+margin*2,scale,options);
if (bounds) that.setBounds(bounds.x, bounds.y, bounds.width, bounds.height);
return that;
}
this.childrenToBitmap = function() {
var cached = this.cacheCanvas;
var pic = new zim.Bitmap(this.cache().cacheCanvas);
if (!cached) this.uncache();
this.removeAllChildren();
pic.addTo(this);
return this;
}
var frame = zimDefaultFrame || 1;
if (createjs && !createjs.stageTransformable && frame.retina) {
this.localToGlobal = function(x,y) {
return zim.localToGlobal(x,y,this,this.cjsContainer_localToGlobal);
}
this.globalToLocal = function(x,y) {
return zim.globalToLocal(x,y,this,this.cjsContainer_globalToLocal);
}
this.localToLocal = function(x,y,target) {
return zim.localToLocal(x,y,target,this);
}
}
this.setBounds = function(a,b,c,d) {
var n = normalizeBounds(a, b, c, d);
this.cjsContainer_setBounds(n[0],n[1],n[2],n[3]);
return this;
}
if (style!==false) zimStyleTransforms(this, DS); // global function - would have put on DisplayObject if had access to it
this.clone = function(exact) {
var currentBounds = this.getBounds();
if (zot(currentBounds)) currentBounds = {x:null, y:null, width:null, height:null};
return this.cloneChildren(this.cloneProps(new zim.Container(currentBounds.x,currentBounds.y,currentBounds.width,currentBounds.height, style, this.group, inherit)), exact);
}
this.hasProp = function(prop) {
return (!zot(this[prop]) || this.hasOwnProperty(prop))
}
}
zim.Container.prototype.dispose = function(disposing) {
recursiveDispose(this, disposing);
return true;
}
zim.Container.prototype.specialColor = function(command, co) {
if (co.type=="GradientColor") command.linearGradient(co.colors, co.ratios, co.x0, co.y0, co.x1, co.y1);
else if (co.type=="RadialColor") command.radialGradient(co.colors, co.ratios, co.x0, co.y0, co.r0, co.x1, co.y1, co.r1);
else if (co.type == "BitmapColor") command.bitmap(co.image, co.repetition, co.matrix);
}
function recursiveDispose(obj, disposing) {
// dispose was fixed in ZIM 10.7.0 in TWO ways:
// ONE
// Some classes have custom dispose - so may want to call these.
// If disposing is true then we are coming from a custom dispose already
// otherwise, call the custom dispose and pass true to say we are already disposing containers
// otherwise the custom dispose will try and call the container dispose and we have an endless loop
if (!disposing && obj.dispose && obj.dispose !== zim.Container.prototype.dispose) {
obj.dispose(null,null,true);
}
// TWO
// dispose was only disposing type=="CONTAINER"
// so should have been type=="Container" - but even that is too narrow
// as would not include components parts or Tile parts, etc.
// so fixed it to include all decendents of Container by testing for addChild
// zog(obj.type)
// if (obj.type == "Container") {
if (obj.addChild) {
obj.dispatchEvent("removed");
obj.removeAllEventListeners();
if (obj.numChildren) {
for (var i=obj.numChildren-1; i>=0; i--) {
recursiveDispose(obj.getChildAt(i));
}
}
}
if (obj.parent) obj.parent.removeChild(obj);
}
zimify(zim.Container.prototype);
zim.extend(zim.Container, createjs.Container, ["cache","setBounds","clone","localToLocal","localToGlobal","globalToLocal"], "cjsContainer", false);
//-50.5
/*--
zim.Shape = function(a, b, c, d, graphics, optimize, style, group, inherit)
Shape
zim class - extends a createjs.Shape
DESCRIPTION
ZIM Shape lets you draw dynamic shapes beyond the ZIM provided shapes.
You make a new shape object and then draw in its graphics property
using similar commands to the HTML Canvas commands (and Flash Bitmap drawing).
See the CreateJS Easel Shapes and Graphics docs:
http://www.createjs.com/docs/easeljs/classes/Graphics.html
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
NOTE: as of ZIM 10.6.0 the tiny API is available right on the Shape (no need for graphics)
EXAMPLE
var shape = new Shape().addTo();
shape.graphics.beginFill(red).drawRect(0,0,200,100);
// similar to Rectangle(200, 100, "Red");
// or we can use the tiny API (see methods)
// NOTE: these can be chained directly on the Shape object
new Shape().f(red).dr(0,0,200,100).addTo();
// we can draw lines, etc.
var g = shape.graphics; // shorter reference to graphics object
g.beginStroke(blue).moveTo(200,200).lineTo(300,300);
// or we can use the tiny API (see methods)
new Shape().s(blue).ss(5).mt(200,200).lt(300,300).addTo();
// to change a color or stroke after it has been made use command:
var shape = new Shape().addTo();
var strokeColor = shape.s(red).command;
shape.dr(50,50,100,100);
stage.update();
timeout(1000, function(){
strokeColor.style = blue;
stage.update();
});
// note - we can draw as much as we want in the same shape
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
** Shape supports three different sets of parameters as follows:
a - (default null) - width and height equal to parameter a (x and y will be 0)
a, b - (default null) - the width and height (x and y will be 0)
a, b, c, d - (default null) - the x, y, width and height of the bounds
graphics - (default null) a CreateJS Graphics instance (see CreateJS docs)
or just use the graphics property of the shape object (like usual)
optimize - (default false) set to true to not store graphics methods directly on Shape
this means the shapes graphics property will need to be used to access f(), s(), ss(), etc.
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
The following shortcuts to CreateJS graphics methods are provided (as long as optimize is false)
See https://www.createjs.com/docs/easeljs/classes/Graphics.html for definitions and parameters
mt() moveTo
lt() lineTo
a() arc
at() arcTo
bt() bezierCurveTo
qt() quadraticCurveTo
r() rect
cp() closePath
c() clear
f() beginFill
lf() beginLinearGradientFill
rf() beginRadialGradientFill
bf() beginBitmapFill
ef() endFill
ss() setStrokeStyle
sd() setStrokeDash
s() beginStroke
ls() beginLinearGradientStroke
rs() beginRadialGradientStroke
bs() beginBitmapStroke
es() endStroke
dr() drawRect
rr() drawRoundRect
rc() drawRoundRectComplex
dc() drawCircle
de() drawEllipse
dp() drawPolyStar
p() decodePath
cache(width||x, height||y, null||width, null||height, scale, options, margin) - overrides CreateJS cache() and returns object for chaining
If you do not provide the first four parameters, then the cache dimensions will be set to the bounds of the object
width||x - (default getBounds().x) the width of the chache - or the x if first four parameters are provided
height||y - (default getBounds().y) the height of the chache - or the y if first four parameters are provided
width - (default getBounds().width) the width of the chache - or null if first two parameters are provided
height - (default getBounds().height) the height of the chache - or null if first two parameters are provided
scale - (default 1) set to 2 to cache with twice the fidelity if later scaling up
options - (default null) additional parameters for cache logic - see CreateJS somewhere for details
margin - (default 0) add or subtract a margin from the bounds
eg. margin:10 will make the cache size 10 pixels more on all sides
this can be handy when caching objects with borders - that go half outside the natural bounds
setBounds(width||x, height||y, null||width, null||height) - overrides CreateJS setBounds() and returns object for chaining
width||x - (default null) the width of the bounds - or the x if four parameters are provided
height||y - (default width) the height of the bounds - or the y if four parameters are provided
width - (default null) the width of the bounds - or null if only the first two parameters are provided
height - (default null) the height of the bounds - or null if only the first two parameters are provided
hasProp(property) - returns true if String property exists on object else returns false
clone(recursive) - makes a copy of the shape
recursive defaults to true so copy will have own copy of graphics
set recursive to false to have clone share graphic property
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), placeReg(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
command - save a previously chained operation as a command
then can use the command to change the operation later (see example above)
type - holds the class name as a String
** bounds must be set first (or width and height parameters set) for these to work
** setting these adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
depth - for ZIM VR - the depth used to shift left and right channel and for parallax in VR - also see dep() ZIM Display method
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Shape properties, such as:
graphics, x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseEnabled, etc.
EVENTS
See the CreateJS Easel Docs for Shape events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+50.6
zim.Shape = function(a, b, c, d, graphics, optimize, style, group, inherit) {
var sig = "a, b, c, d, graphics, optimize, style, group, inherit";
var duo; if (duo = zob(zim.Shape, arguments, sig, this)) return duo;
z_d("50.6");
this.cjsShape_constructor(graphics);
this.type = "Shape";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
var that = this;
if (zot(a)) a = DS.a!=null?DS.a:null;
if (zot(b)) b = DS.b!=null?DS.b:null;
if (zot(c)) c = DS.c!=null?DS.c:null;
if (zot(d)) d = DS.d!=null?DS.d:null;
if (zot(graphics)) graphics = DS.graphics!=null?DS.graphics:null;
if (zot(optimize)) optimize = DS.optimize!=null?DS.optimize:false;
var n = normalizeBounds(a, b, c, d);
function normalizeBounds(a, b, c, d) {
var bounds = [];
if (!zot(c)) {
bounds[0] = a;
bounds[2] = c;
bounds[1] = b;
bounds[3] = d;
} else {
bounds[0] = 0;
bounds[2] = a;
bounds[1] = 0;
bounds[3] = b;
}
if (zot(bounds[3])) bounds[3] = bounds[2];
return bounds;
}
if (!zot(a)) this.setBounds(n[0],n[1],n[2],n[3]); // es6 to fix
if (!optimize) {
var shorts = ["mt","lt","a","at","bt","qt","cp","c",
"f","lf","rf","bf","ef","ss","sd","s",
"ls","rs","bs","es","dr","rr","rc","dc","de","dp","p"];
for (var i=0; i 0 ? that.borderWidth/2 : 0;
a = bounds.x-added;
b = bounds.y-added;
c = bounds.width+added*2;
d = bounds.height+added*2;
}
} else {
c = a;
d = b;
a = 0;
b = 0;
}
}
if (zot(margin)) margin = 0;
that.cjsShape_cache(a-margin,b-margin,c+margin*2,d+margin*2,scale,options);
return that;
}
this.setBounds = function(a,b,c,d) {
var n = normalizeBounds(a, b, c, d);
this.cjsShape_setBounds(n[0],n[1],n[2],n[3]);
return this;
}
if (style!==false) zimStyleTransforms(this, DS); // global function - would have put on DisplayObject if had access to it
this.clone = function(recursive) {
if (zot(recursive)) recursive = true;
var currentBounds = this.getBounds();
if (zot(currentBounds)) currentBounds = {x:null, y:null, width:null, height:null};
var c = that.cloneProps(new zim.Shape(currentBounds.x,currentBounds.y,currentBounds.width,currentBounds.height, graphics, style, group, inherit));
if (recursive) c.graphics = that.graphics.clone();
else c.graphics = that.graphics;
return c;
}
var frame = zimDefaultFrame || 1;
if (createjs && !createjs.stageTransformable && frame.retina) {
this.localToGlobal = function(x,y) {
return zim.localToGlobal(x,y,this,this.cjsShape_localToGlobal);
}
this.globalToLocal = function(x,y) {
return zim.globalToLocal(x,y,this,this.cjsShape_globalToLocal);
}
this.localToLocal = function(x,y,target) {
return zim.localToLocal(x,y,target,this);
}
}
this.hasProp = function(prop) {
return (!zot(this[prop]) || this.hasOwnProperty(prop))
}
this.dispose = function(a,b,disposing) {
this.graphics.c();
this.dispatchEvent("removed");
this.removeAllEventListeners();
if (this.parent) this.parent.removeChild(this);
}
}
zim.extend(zim.Shape, createjs.Shape, ["cache","clone","setBounds","localToLocal","localToGlobal","globalToLocal"], "cjsShape", false);
zimify(zim.Shape.prototype);
//-50.6
/*--
zim.Bitmap = function(image, width, height, id, style, group, inherit)
Bitmap
zim class - extends a createjs.Bitmap
DESCRIPTION
Makes a Bitmap object from an image.
It is best to use the assets and path parameters of ZIM Frame or the loadAssets() method of Frame
to preload the image and then use the asset() method to access the Bitmap.
See the ZIM Frame class and asset example on the ZIM Frame page of templates.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var frame = new Frame();
frame.on("ready", function() {
var stage = frame.stage;
frame.loadAssets("logo.jpg");
frame.on("complete", function() {
var logo = frame.asset("logo.jpg"); // logo is a Bitmap
logo.center();
stage.update();
});
});
END EXAMPLE
EXAMPLE
// turn a container of circles into a Bitmap
var circles = new Container(stageW, stageH).addTo();
loop(400, function() {
new Circle(rand(10), [pink,green,blue,yellow,purple], dark).center(circles);
});
var pic = new Bitmap(circles).drag();
circles.dispose();
previous to ZIM 10.8.0 we needed to use the cacheCanvas:
var pic = new Bitmap(circles.cache().cacheCanvas).drag();
curcles.uncache(); etc.
END EXAMPLE
EXAMPLE
// fill a Bitmap with noise:
var noise = new Noise();
// empty Bitmap size 200, 200
var bmp = new Bitmap(null,200,200).center(stage);
// we fill the bitmap starting from top left going across in the inner loop,
// then down, then across, etc. until we get to bottom right.
var f = 50; // used to make noise bigger or smaller - see the blob comment below
for (var y = 0; y < bmp.height; y++) {
for (var x = 0; x < bmp.width; x++) {
// the noise methods return a number from -1 to 1
// by adding 1 we get a number between 0 and 2 then divide by 2
// and we multiply this by 255 to get a number between 0 and 255
value = (noise.simplex2D(x, y)+1)/2 * 255;
// or get blobs by smoothing and adjusting frequency:
// var value = smoothStep((noise.simplex2D(x/f, y/f)+1)/2, .3,.35) * 255;
// imageData is four values per pixel
// the red, green, blue and alpha
// in one big long array - each value will be constrained to between 0 and 255
// this i value will increase by 4 each time
// then we write the same value for red, green, blue to get a shade of grey
var i = (x + y * bmp.width) * 4;
bmp.imageData.data[i] = value; // red (0-255)
bmp.imageData.data[i + 1] = value; // green (0-255)
bmp.imageData.data[i + 2] = value; // blue (0-255)
bmp.imageData.data[i + 3] = 255; // alpha (0-255)
}
}
bmp.drawImageData();
END EXAMPLE
EXAMPLE
// applying filters
var bitmap = frame.asset("statue.jpg");
bitmap.filters = [new createjs.BlurFilter(25, 25, 1)];
bitmap.cache().center();
END EXAMPLE
EXAMPLE
// getting the color at point(100, 100) on the Bitmap
var bitmap = frame.asset("statue.jpg").cache();
var ctx = bitmap.cacheCanvas.getContext('2d');
var data = ctx.getImageData(100, 100, 1, 1).data;
var color = "rgba("+data.join(", ")+")";
END EXAMPLE
EXAMPLE
// a Base64 image:
var image = "data:image/png;base64,longlistofcharacters";
var logo;
Bitmap.fromData(image, function (bitmap) {
logo = bitmap.center();
stage.update();
});
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
image - an HTML image URL (may not load right away - see Frame loadAssets)
or as of 10.8.0 a DisplayObject - this will be turned into a cacheCanvas
and then the DisplayObject turned back to its previous cached setting
width - (default 100) used with putImageData to draw a Bitmap otherwise ignored
height - (default 100) used with putImageData to draw a Bitmap otherwise ignored
id - an optional id
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
fromData(data, callback) - STATIC method so use the Bitmap class directly: Bitmap.fromData()
The callback will receive a reference to the Bitmap after 50ms or 100ms.
There is no event for making a Bitmap from base64 for instance - so this will have to do.
drawImageData(x, y, sourceX, srcY, srcWidth, srcHeight) - draws the Bitmap's imageData data to the Bitmap
NOTE: This is only used when dynamically drawing a Bitmap with data - not for your normal picture
See the imageData property which should be set before using the drawImageData() method
ZIM calls a putImageData method for the HTML Canvas and then transfers this to the Bitmap
See also https://www.w3schools.com/tags/canvas_putimagedata.asp - but let ZIM do the work...
cache(width||x, height||y, null||width, null||height, scale, options) - overrides CreateJS cache() and returns object for chaining
** Usually you do not want to cache a Bitmap as it is already a Bitmap ;-)
** But for applying a filter or using a cacheCanvas to get a context, etc. then you might.
If you do not provide the first four parameters, then the cache dimensions will be set to the bounds of the object
width||x - (default getBounds().x) the width of the chache - or the x if first four parameters are provided
height||y - (default getBounds().y) the height of the chache - or the y if first four parameters are provided
width - (default getBounds().width) the width of the chache - or null if first two parameters are provided
height - (default getBounds().height) the height of the chache - or null if first two parameters are provided
scale - (default 1) set to 2 to cache with twice the fidelity if later scaling up
options - (default null) additional parameters for cache logic - see CreateJS somewhere for details
getColorAt(x,y) - returns the rgba() value at the x and y location
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Bitmap methods, such as:
on(), off(), getBounds(), setBounds(), dispatchEvent(), etc.
PROPERTIES
type - holds the class name as a String
imageData - data for the pixels stored in a data property of an ImageData object
NOTE: This is only used when dynamically drawing a Bitmap with data - not for your normal picture
The data property is an one dimensional Array with consecutive red, green, blue, alpha values (0-255) for each pixels
eg. 0,0,0,255,255,255,255,255 is a black pixel with 1 alpha and a white pixel with 1 alpha
You set this before calling the Bitmap drawImageData() method
See also https://developer.mozilla.org/en-US/docs/Web/API/ImageData - but let ZIM do the work
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
depth - for ZIM VR - the depth used to shift left and right channel and for parallax in VR - also see dep() ZIM Display method
id (fileID in TypeScript) - the filename used in the frame.loadAssets()
if you add the path the file name then it will be included with the id
if you add the path with the path parameter, it will not be included with the id
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Bitmap properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseEnabled, etc.
EVENTS
See the CreateJS Easel Docs for Bitmap events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+50.7
zim.Bitmap = function(image, width, height, id, style, group, inherit) {
var sig = "image, width, height, id, style, group, inherit";
var duo; if (duo = zob(zim.Bitmap, arguments, sig, this)) return duo;
z_d("50.7");
if (!zot(image)) {
if (image.uncache) { // testing if it has a CreateJS uncache method
var cached = image.cacheCanvas;
var original = image;
image = image.cache().cacheCanvas; // what we will pass to bitmap
}
}
this.cjsBitmap_constructor(image);
if (original && !cached) original.uncache();
var that = this;
this.type = "Bitmap";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
this.id = that.fileID = DS.id!=null?DS.id:id;
if (zot(width)) width = DS.width!=null?DS.width:null;
if (zot(height)) height = DS.height!=null?DS.height:null;
if (!zot(width) && !zot(height)) that.setBounds(0,0,width,height);
if (zot(width)) width = 100;
if (zot(height)) height = 100;
if (zimDefaultFrame) {
// not supported by IE - thanks Chris Spolton for the find and suggested fix
if (zimDefaultFrame.canvas.getContext("2d")) {
this.imageData = zimDefaultFrame.canvas.getContext("2d").createImageData(width, height);
} else {
this.imageData = document.createElement('canvas').getContext("2d").createImageData(width, height);
// if (ImageData) this.imageData = new ImageData(width, height);
}
this.drawImageData = function(x, y, sourceX, sourceY, sourceWidth, sorceHeight) {
if (zot(x)) x = 0;
if (zot(y)) y = 0;
if (zot(sourceX)) sourceX = 0;
if (zot(sourceY)) sourceY = 0;
if (zot(sourceWidth)) sourceWidth = width;
if (zot(sorceHeight)) sorceHeight = height;
if (!that.proxyCanvas) {
var c = that.proxyCanvas = document.createElement("canvas");
c.setAttribute("width", width);
c.setAttribute("height", height);
that.proxyContext = c.getContext('2d');
image = that.image = c;
}
if (that.proxyContext) {
that.proxyContext.putImageData(that.imageData, x, y, sourceX, sourceY, sourceWidth, sorceHeight);
}
}
if (zot(image)) that.drawImageData();
// handle delay when creating Bitmap from data
if (image.match && image.match(/data:image/i)) setTimeout(function() {
if (that.stage) that.stage.update();
setTimeout(function() {
if (that.stage) that.stage.update();
}, 50);
}, 50);
}
this.cache = function(a,b,c,d,scale,options) {
if (zot(c)) {
if (zot(a)) {
var bounds = this.getBounds();
if (!zot(bounds)) {
var added = this.borderWidth > 0 ? this.borderWidth/2 : 0;
a = bounds.x-added;
b = bounds.y-added;
c = bounds.width+added*2;
d = bounds.height+added*2;
}
} else {
c = a;
d = b;
a = 0;
b = 0;
}
}
var bounds = this.getBounds();
this.cjsBitmap_cache(a,b,c,d,scale,options);
this.setBounds(bounds.x, bounds.y, bounds.width, bounds.height);
return this;
}
if (style!==false) zimStyleTransforms(this, DS); // global function - would have put on DisplayObject if had access to it
this.clone = function() {
return this.cloneProps(new zim.Bitmap(image, null, null, that.fileID, style, this.group, inherit));
}
var frame = zimDefaultFrame || 1;
if (createjs && !createjs.stageTransformable && frame.retina) {
this.localToGlobal = function(x,y) {
return zim.localToGlobal(x,y,this,this.cjsBitmap_localToGlobal);
}
this.globalToLocal = function(x,y) {
return zim.globalToLocal(x,y,this,this.cjsBitmap_globalToLocal);
}
this.localToLocal = function(x,y,target) {
return zim.localToLocal(x,y,target,this);
}
}
this.hasProp = function(prop) {
return (!zot(this[prop]) || this.hasOwnProperty(prop))
}
var myContext;
this.getColorAt = function(x,y) {
if (!myContext) {
that.cache();
myContext = that.cacheCanvas.getContext('2d');
that.uncache();
}
var d = myContext.getImageData(x, y, 1, 1).data;
return "rgba("+d[0]+","+d[1]+","+d[2]+","+d[3]+")";
}
this.dispose = function(a,b,disposing) {
this.dispatchEvent("removed");
this.removeAllEventListeners();
if (this.parent) this.parent.removeChild(this);
}
}
zim.Bitmap.fromData = function(data, callback) {
var bitmap = new zim.Bitmap(data);
setTimeout(function() {
callback(bitmap);
}, 50);
}
zim.extend(zim.Bitmap, createjs.Bitmap, ["cache","clone","localToLocal","localToGlobal","globalToLocal"], "cjsBitmap", false);
zimify(zim.Bitmap.prototype);
//-50.7
/*--
zim.Sprite = function(image, cols, rows, count, offsetX, offsetY, spacingX, spacingY, width, height, animations, json, id, globalControl, spriteSheet, label, style, group, inherit)
Sprite
zim class - extends a createjs.Sprite
DESCRIPTION
A Sprite plays an animation of a spritesheet
which is a set of images layed out in one file.
You play the Sprite with the run() method.
This animates the Sprite over a given time
with various features like playing a labelled animation,
playing animation series,
SEE: https://zimjs.com/spritesheet/index.html
AND: https://zimjs.com/spritesheet/skateboard.html
wait, loop, rewind and call functions.
This actually runs a ZIM animation and animates the frames.
NOTE: A ZIM Sprite handles both an evenly tiled spritesheet - use cols and rows
and an un-evenly tiled spritesheet - use the json parameter.
The json can come from TexturePacker for instance exported for EaselJS/CreateJS
CreateJS Easel Sprite and SpriteSheet docs:
http://www.createjs.com/docs/easeljs/classes/Sprite.html
http://www.createjs.com/docs/easeljs/classes/SpriteSheet.html
You can optionally pass in an existing createjs.SpriteSheet as a parameter.
When you do so, all other parameters are ignored.
NOTE: You can use CreateJS gotoAndPlay(), play(), etc.
but we found the framerate could not be kept
with other animations or Ticker events running.
So we recommend using the ZIM Sprite run() method.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// inside Frame template
// boom.png is a sprite sheet found online
// It has 8 columns and 6 rows that we can visually count
// We can enter a total parameter if it does not end evenly in the grid
// A graphics editor (like Photoshop) could be used to see
// if there is an offset or spacing, etc. and enter those as parameters
// In this case, we do not need to do any of this - just enter the cols and rows
var scaling = "fit"; // this will resize to fit inside the screen dimensions
var width = 1024;
var height = 768;
var color = light;
var outerColor = darker;
var assets = ["boom.png"];
var path = "assets/";
var frame = new Frame(scaling, width, height, color, outerColor, assets, path); // note we add the assets and path
frame.on("complete", function() {
var spriteImage = asset("boom.png"); // may want to test this first with a .center();
var animation = new Sprite({
image:spriteImage,
cols:8,
rows:6,
animations:{mid:[10,20], end:[30,40]} // optional animations with labels
// see CreateJS SpriteSheet docs for the various animation format as there are a few different ones!
}).center().run(2000); // plays the frames of the Sprite over 2 seconds (master time)
// OR use the label to play the frames listed in animations parameter
animation.run(1000, "mid");
// OR run a series of animations
// by passing an array of label objects to the label parameter
// these each have a time so the master time is ignored
// they can also have any of the run() parameters
// if you provide an array of labels, you cannot rewind the overall animation
animation.run(null, [
{label:"mid", time:1000},
{label:"end", time:500, loop:true, loopCount:5, call:function(){zog("loops done");}},
{startFrame:10, endFrame:20, time:1000}
]);
// OR can call a function when done
animation.run(1000, "mid", function(){
stage.removeChild(animation);
stage.update();
});
// OR can loop the animation
animation.run({time:2000, loop:true}); // see run() parameters for more
});
END EXAMPLE
EXAMPLE
// using Sprite as a texture atlas - or spritesheet of different images
// see: https://zimjs.com/explore/fruit.html
// load in assets and path
var frame = new Frame({assets:["fruit.png", "fruit.json"], path:"assets/"});
frame.on("ready", function() {
new Sprite({json:asset("fruit.json"), label:"apple"}).center();
frame.stage.update();
});
END EXAMPLE
EXAMPLE
// Here is an example with CreateJS SpriteSheet data
// robot.png is a sprite sheet made by ZOE based on a Flash swf
// you can also make your own with Photoshop or Texture Packer
frame.loadAssets("robot.png");
frame.on("complete", function() {
// using ZOE to export swf animation to spritesheet data
// spritesheet data uses the image name, not the Bitmap itself
var image = asset("robot.png").image;
var spriteData = {
"framerate":24,
"images":[image],
"frames":[[0, 0, 256, 256, 0, -54, -10], many more - etc.],
"animations":{}
};
var animation = new Sprite({json:spriteData})
.center()
.run(2000); // note, duration alternative to framerate
});
OR
// load in data from external JSON
frame.loadAssets(["robot.json", "robot.png"]);
// ... same as before
var animation = new Sprite({json:asset("robot.json")});
// ... same as before
// see CreateJS SpriteSheet docs for the format of the JSON file
// including various animation formats
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
image - the ZIM Bitmap for the spritesheet
cols - (default 1) - the columns in the spritesheet
rows - (default 1) the rows in the spritesheet
count - (default cols*rows) how many total frames in the spritesheet
offsetX - (default 0) the pixels from the left edge to the frames
offsetY - (default 0) the pixels from the top edge to the frames
spacingX - (default 0) the horizontal spacing between the frames
spacingY - (default 0) the vertical spacing between the frames
width - (default image width) the width including offset and spacing for frames
height - (default image height) the height including offset and spacing for frames
animations - (default null) an object literal of labels holding frames to play
{label:3, another:[4,10]}
run(1000, "label") would play frame 3 for a second
run(1000, "another") would play frames 4 to 10 for a second
{unordered:{frames:[1,2,3,22,23,24,"anotherLabel",5,6], next:prevLabel}}
There are also ways to set speeds - but would recommend dividing into simple labels
and using the label series technique available with the run() method
json - (default null) a JSON string for a CreateJS SpriteSheet
If you pass in a json parameter, all other parameters are ignored
NOTE: remember that JSON needs quotes around the animation properties above:
{"label":3, "another":[4,10]}
id - (default randomly assigned) an id you can use in other animations - available as sprite.id
use this id in other animations for pauseRun and stopRun to act on these as well
globalControl - (default true) pauseRun and stopRun will control other animations with same id
spriteSheet - (default null) pass in a CreateJS SpriteSheet to build a Sprite from that
label - (default null) pass in a label to stop on initially - to play from a label use the run({label:val}) method
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
run(time, label, call, params, wait, waitedCall, waitedParams, loop, loopCount, loopWait, loopCall, loopParams, loopWaitCall, loopWaitParams, loopPick, rewind, rewindWait, rewindCall, rewindParams, rewindWaitCall, rewindWaitParams, rewindTime, rewindEase, startFrame, endFrame, tweek, id, globalControl)
The run() method animates the Sprite over an amount of time
Would recommend this method over the CreateJS play() and gotoAndPlay()
methods because the framerate for these get overwritten by other stage.update() calls
With run() you get other nice ZIM animate features as well as follows:
Returns the object for chaining
Can be paused with pauseAnimate(true) or unpaused with pauseAnimate(false)
Can be stopped with stopAnimate() on the Sprite
supports DUO - parameters or single object with properties below
time (default 1000) - the time in milliseconds to run the animations (the master time)
label (default null) - a label specified in the Sprite animations parameter
if this is an array holding label objects for example:
[{label:"run", time:1000}, {label:"stand", time:2000}]
then the sprite will play the series with the times given and ignore the master time
Note: if any of the series has a loop and loops forever (a loopCount of 0 or no loopCount)
then this will be the last of the series to run
rewind is not available on the outside series but is available on an inside series
call - (default null) the function to call when the animation is done
params - (default target) a single parameter for the call function (eg. use object literal or array)
wait - (default 0) milliseconds to wait before doing animation
waitedCall - (default null) call the function after a wait time if there is one
waitedParams - (default null) parameters to pass to the waitedCall function
loop - (default false) set to true to loop animation
loopCount - (default 0) if loop is true how many times it will loop (0 is forever)
loopWait - (default 0) milliseconds to wait before looping (post animation wait)
loopCall - (default null) calls function after loop and loopWait (not including last loop)
loopParams - (default target) parameters to send loopCall function
loopWaitCall - (default null) calls function after at the start of loopWait
loopWaitParams - (default target) parameters to send loopWaitCall function
rewind - (default false) set to true to rewind (reverse) animation (doubles animation time) (not available on label series)
rewindWait (default 0) milliseconds to wait in the middle of the rewind
rewindCall (default null) calls function at middle of rewind after rewindWait
rewindParams - (default target) parameters to send rewindCall function
rewindWaitCall (default null) calls function at middle of rewind before rewindWait
rewindWaitParams - (default target) parameters to send rewindCall function
rewindTime - (default time) set to a time in ms to adjust the time to rewind
rewindEase - (default null) see ease parameter for options for rewind ease
note - this goes backwards - so "bounceOut" would happen at the end of the rewind
startFrame - (default null - or 0) the frame to start on - will be overridden by a label with frames
endFrame - (default null - or totalFrames) the frame to end on - will be overridden by a label with frames
tweek - (default 1) a factor for extra time on rewind and loops if needed
id - (default randomly assigned) an id you can use in other animations - available as sprite.id
use this id in other animations for pauseRun and stopRun to act on these as well
globalControl - (default true) pauseRun and stopRun will control other animations with same id
pauseRun(state) - pause or unpause the animation (including an animation series)
state - (default true) when true the animation is paused - set to false to unpause
returns object for chaining
stopRun() - stop the sprite from animating
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Sprite methods, such as:
play(), gotoAndPlay(), gotoAndStop(), stop(), advance(),
on(), off(), getBounds(), setBounds(), dispatchEvent(), etc.
PROPERTIES
id - an id that you can use in other animations to also be controlled by pauseRun() and stopRun()
frame - get and set the current frame of the Sprite
normalizedFrame - if animations have CreateJS speeds applied, zim handles these by making extra frames
for example, if a speed is given of .5 then two frames are made (min resulution is .1)
normalizedFrames - an array of total frames after being normalized - really for internal usage
totalFrames - get the total frames of the Sprite - read only
animations - the animations data with labels of frames to animate
running - is the sprite animation being run (includes both paused and unpaused) - read only
runPaused - is the sprite animation paused (also returns paused if not running) - read only
note: this only syncs to pauseRun() and stopRun() not pauseAnimate() and stopAnimate()
note: CreateJS has paused, etc. but use that only if running the CreateJS methods
such as gotoAndPlay(), gotoAndStop(), play(), stop()
** bounds must be set first for these to work
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
depth - for ZIM VR - the depth used to shift left and right channel and for parallax in VR - also see dep() ZIM Display method
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Sprite properties, such as:
currentFrame, framerate, paused, currentAnimation, currentAnimationFrame, spriteSheet,
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseEnabled, etc.
EVENTS
See the CreateJS Easel Docs for Sprite events, such as:
animationend, change, added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+50.8
zim.Sprite = function(image, cols, rows, count, offsetX, offsetY, spacingX, spacingY, width, height, animations, json, id, globalControl, spriteSheet, label, style, group, inherit) {
var sig = "image, cols, rows, count, offsetX, offsetY, spacingX, spacingY, width, height, animations, json, id, globalControl, spriteSheet, label, style, group, inherit";
var duo; if (duo = zob(zim.Sprite, arguments, sig, this)) return duo;
z_d("50.8");
this.type = "Sprite";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
var that = this;
var sheet;
if (zot(json) && !zot(image)) {
if (zot(cols)) cols = DS.cols!=null?DS.cols:1;
if (zot(rows)) rows = DS.rows!=null?DS.rows:1;
if (zot(count)) count = DS.count!=null?DS.count:(cols*rows);
if (zot(offsetX)) offsetX = DS.offsetX!=null?DS.offsetX:0;
if (zot(offsetY)) offsetY = DS.offsetY!=null?DS.offsetY:0;
if (zot(spacingX)) spacingX = DS.spacingX!=null?DS.spacingX:0;
if (zot(spacingY)) spacingY = DS.spacingY!=null?DS.spacingY:0;
if (zot(width)) width = DS.width!=null?DS.width:image.width;
if (zot(height)) height = DS.height!=null?DS.height:image.height;
var frameW = (width-offsetX+spacingX) / cols - spacingX;
var frameH = (height-offsetY+spacingY) / rows - spacingY;
var frames = [];
var num = 0;
outer:
for (var j=0; j count) break outer;
frames.push([
offsetX + i*(frameW+spacingX),
offsetY + j*(frameH+spacingY),
frameW,
frameH
]);
}
}
makeSheet(image, frames, animations);
} else if (spriteSheet) {
sheet = spriteSheet;
animations = sheet.animations;
} else if (json) {
// even though data is in JSON, may want to create SpriteSheet from image
// so that cors will work - so see if provided an image
// or that the images in the JSON are available in frame.assets
frames = json.frames;
animations = json.animations;
if (!zot(image)) {
makeSheet(image, frames, animations);
} else {
var im = json.images?json.images[0]:null;
if (!im.split) {
sheet = new createjs.SpriteSheet(json);
} else {
var imEnd = im.split("/").pop();
if (frame.asset(imEnd).type != "EmptyAsset") {
makeSheet(frame.asset(imEnd), frames, animations);
} else if (frame.asset(im).type != "EmptyAsset") {
var imFinal = frame.asset(im);
makeSheet(frame.asset(im), frames, animations);
} else {
sheet = new createjs.SpriteSheet(json);
}
}
}
} else {
return;
}
function makeSheet(image, frames, animations) {
var spriteData = {
images:[image.image], // note, this takes the image, not the Bitmap
frames:frames,
animations:animations?animations:[]
};
sheet = new createjs.SpriteSheet(spriteData);
}
this.animations = animations;
this.cjsSprite_constructor(sheet, label);
if (!zot(label)) this.stop();
if (zot(id)) id = zim.makeID();
this.id = id;
if (zot(globalControl)) globalControl = true;
that.globalControl = globalControl;
var _normalizedFrame = 0;
var _normalizedFrames;
this.parseFrames = function(label, startFrame, endFrame, fromDynamo) {
var frames = [];
var minSpeed = Number.MAX_VALUE;
var maxSpeed = 0;
if (zot(label)) {
if (zot(startFrame)) startFrame = 0;
if (zot(endFrame)) endFrame = that.totalFrames-1;
addSequential(startFrame, endFrame);
} else {
if (zot(that.animations) || zot(that.animations[label])) return [];
var a = that.animations[label];
processAnimation(a);
}
function processAnimation(a) {
if (Array.isArray(a)) {
processArray(a);
} else if (a.constructor == {}.constructor) {
processObject(a);
} else if (!isNaN(a)) {
frames.push({f:Math.floor(a), s:1});
}
}
function processArray(a) {
addSequential(a[0], a[1], a[3]);
if (a[2] && !zot(that.animations[a[2]])) processAnimation(that.animations[a[2]]);
}
function processObject(a) {
if (zot(a.frames)) return;
if (zot(a.speed)) a.speed = 1;
for (var i=0; i maxSpeed) maxSpeed = a.speed;
frames.push({f:a.frames[i], s:a.speed});
}
if (a.next && !zot(that.animations[a.next])) processAnimation(that.animations[a.next]);
}
function addSequential(start, end, speed) {
if (zot(speed)) speed = 1;
if (end > start) {
for (var i=start; i<=end; i++) {inner(i);}
} else {
for (var i=end; i<=start; i++) {inner(start-(i-end));}
}
function inner(i) {
if (speed < minSpeed) minSpeed = speed;
if (speed > maxSpeed) maxSpeed = speed;
frames.push({f:i, s:speed});
}
}
if (fromDynamo) return frames;
// run() uses an array of frame numbers (normalized to speed) where dynamo uses the speed
// normalize up to 1/10 - as in if put at .1 then have to multiply all others speeds by 10
minSpeed = zim.constrain(zim.decimals(minSpeed), .1);
maxSpeed = zim.constrain(zim.decimals(maxSpeed), .1);
// normalize speed:
var framesNormalized = [];
var normalize = (minSpeed != maxSpeed);
var fr;
for (var i=0; i 0) extraTime = tt / (endFrame-startFrame) / 2; // slight cludge - seems to look better?
// if (i==0) firstStartFrame = startFrame;
}
//startFrame = firstStartFrame;
if (obj.length == 0) return this;
if (obj.length == 1) { // just one label in list ;-)
time = obj[0].time;
label = lastLabel;
setSingle();
} else {
that.gotoAndStop(firstStartFrame);
}
} else { // single label
setSingle();
}
function setSingle() {
_normalizedFrames = that.parseFrames(label, startFrame, endFrame);
_normalizedFrame = 0;
that.gotoAndStop(_normalizedFrames[_normalizedFrame]);
startFrame = endFrame = null;
obj = {normalizedFrame:_normalizedFrames.length-1};
}
if (zot(time)) time = 1000;
// if already running the sprite then stop the last run
if (that.running) that.stopAnimate(that.id);
that.running = true;
if (!Array.isArray(obj)) {
var extraTime = 0;
if (endFrame-startFrame > 0) extraTime = time / Math.abs(endFrame-startFrame) / 2; // slight cludge - seems to look better?
if (_normalizedFrames && _normalizedFrames.length>0) extraTime = time / _normalizedFrames.length / 2; // slight cludge - seems to look better?
if (zot(loopWait)) {loopWait = extraTime*tweek};
if (zot(rewindWait)) {rewindWait = extraTime*tweek};
}
// locally override call to add running status after animation done
var localCall = function() {
if (call && typeof call == 'function') call(params||that);
that.running = false;
that.stop();
}
zim.animate({
target:that,
obj:obj,
time:time,
ease:"linear",
call:localCall,
params:params,
wait:wait, waitedCall:waitedCall, waitedParams:waitedParams,
loop:loop,
loopCount:loopCount,
loopWait:loopWait,
loopCall:loopCall, loopParams:loopParams,
loopWaitCall:loopWaitCall, loopWaitParams:loopWaitParams,
rewind:rewind, rewindWait:rewindWait, // rewind is ignored by animation series
rewindCall:rewindCall, rewindParams:rewindParams,
rewindWaitCall:rewindWaitCall, rewindWaitParams:rewindWaitParams,
rewindTime:rewindTime, rewindEase:rewindEase,
override:false,
id:that.id
});
that.runPaused = false;
return that;
}
this.runPaused = true;
this.pauseRun = function(paused) {
if (zot(paused)) paused = true;
that.runPaused = paused;
if (that.globalControl) {
zim.pauseAnimate(paused, that.id);
} else {
that.pauseAnimate(paused, that.id);
}
return that;
}
this.stopRun = function() {
that.runPaused = true;
that.running = false;
if (that.globalControl) {
zim.stopAnimate(that.id);
} else {
that.stopAnimate(that.id);
}
return that;
}
Object.defineProperty(this, 'frame', {
get: function() {
return this.currentFrame;
},
set: function(value) {
value = Math.round(value);
if (this.paused) {
this.gotoAndStop(value);
} else {
this.gotoAndPlay(value);
}
}
});
Object.defineProperty(this, 'normalizedFrame', {
get: function() {
return _normalizedFrame;
},
set: function(value) {
_normalizedFrame = Math.round(value);
this.gotoAndStop(_normalizedFrames[_normalizedFrame]);
}
});
Object.defineProperty(this, 'normalizedFrames', {
get: function() {
return _normalizedFrames;
},
set: function(value) {
_normalizedFrames = value;
}
});
Object.defineProperty(this, 'totalFrames', {
get: function() {
return sheet.getNumFrames();
},
set: function(value) {
zog("zim.Sprite - totalFrames is read only");
}
});
if (style!==false) zimStyleTransforms(this, DS); // global function - would have put on DisplayObject if had access to it
this.clone = function() {
return this.cloneProps(new zim.Sprite(image, cols, rows, count, offsetX, offsetY, spacingX, spacingY, width, height, animations, json, null, globalControl, spriteSheet, style, this.group, inherit));
}
var frame = zimDefaultFrame || 1;
if (createjs && !createjs.stageTransformable && frame.retina) {
this.localToGlobal = function(x,y) {
return zim.localToGlobal(x,y,this,this.cjsSprite_localToGlobal);
}
this.globalToLocal = function(x,y) {
return zim.globalToLocal(x,y,this,this.cjsSprite_globalToLocal);
}
this.localToLocal = function(x,y,target) {
return zim.localToLocal(x,y,target,this);
}
}
this.hasProp = function(prop) {
return (!zot(this[prop]) || this.hasOwnProperty(prop))
}
this.dispose = function(a,b,disposing) {
this.dispatchEvent("removed");
this.removeAllEventListeners();
if (this.parent) this.parent.removeChild(this);
}
}
zim.extend(zim.Sprite, createjs.Sprite, ["clone","localToLocal","localToGlobal","globalToLocal"], "cjsSprite", false);
zimify(zim.Sprite.prototype);
//-50.8
/*--
zim.MovieClip = function(mode, startPosition, loop, labels, style, group, inherit)
MovieClip
zim class - extends a createjs.MovieClip
DESCRIPTION
A MovieClip adds timelines to a Container.
The timelines are animate() zimTween properties.
The zimTween property returns a CreateJS Tween object.
Primarily made to support Adobe Animate MovieClip export.
*Consider this experimental for the moment...
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var movieClip = new MovieClip();
var circle = new Circle(20, blue).animate({
props:{scale:3}, time:100, rewind:true, loop:true
});
// time is in frames NOT in ms - so 100 frames at the Ticker.framerate 60 fps by default is almost 2 seconds
// note that to change the Ticker's framerate use setFPS(mobile, desktop) method
// if you use one number then both mobile and desktop are set to that fps.
// Note that the defaults are 30 fps mobile and 60 fps desktop
movieClip.timeline.addTween(circle.zimTween);
movieClip.play();
movieClip.center();
stage.on("stagemousedown", function() {
movieClip.paused = !movieClip.paused;
});
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
// from the CreateJS MovieClip docs: http://www.createjs.com/docs/easeljs/classes/MovieClip.html
mode - (default "independent") or single_frame (based on startPosition) or synched (syncs to parent)
startPosition - (default 0) the start position of the MovieClip (*could not get to work)
loop - (default true) set to false not to loop (*did not seem to loop so use loop:true in zim.animate())
labels - (default null) declare label property with position value
eg. {explode:20} to use with gotoAndPlay("explode") rather than gotoAndPlay(20)
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for MovieClip methods, such as:
play(), gotoAndPlay(), gotoAndStop(), stop(), advance(),
on(), off(), getBounds(), setBounds(), dispatchEvent(), etc.
PROPERTIES
type - holds the class name as a String
** bounds must be set first for these to work
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
depth - for ZIM VR - the depth used to shift left and right channel and for parallax in VR - also see dep() ZIM Display method
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for MovieClip properties, such as:
currentFrame, totalFrames, currentLabel, duration, framerate, labels, loop, mode, paused, startPosition, timeline,
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseEnabled, parent, etc.
EVENTS
See the CreateJS Easel Docs for MovieClip events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+50.9
zim.MovieClip = function(mode, startPosition, loop, labels, style, group, inherit) {
var sig = "mode, startPosition, loop, labels, style, group, inherit";
var duo; if (duo = zob(zim.MovieClip, arguments, sig, this)) return duo;
z_d("50.9");
this.type = "MovieClip";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(mode)) mode = DS.mode!=null?DS.mode:null;
if (zot(startPosition)) startPosition = DS.startPosition!=null?DS.startPosition:null;
if (zot(loop)) loop = DS.loop!=null?DS.loop:null;
if (zot(labels)) labels = DS.labels!=null?DS.labels:null;
this.cjsMovieClip_constructor(mode, startPosition, loop, labels);
if (style!==false) zimStyleTransforms(this, DS); // global function - would have put on DisplayObject if had access to it
this.clone = function() {
return this.cloneProps(new zim.MovieClip(mode, startPosition, loop, labels, style, this.group, inherit));
}
this.hasProp = function(prop) {
return (!zot(this[prop]) || this.hasOwnProperty(prop))
}
var frame = zimDefaultFrame || 1;
if (createjs && !createjs.stageTransformable && frame.retina) {
this.localToGlobal = function(x,y) {
return zim.localToGlobal(x,y,this,this.cjsMovieClip_localToGlobal);
}
this.globalToLocal = function(x,y) {
return zim.globalToLocal(x,y,this,this.cjsMovieClip_globalToLocal);
}
this.localToLocal = function(x,y,target) {
return zim.localToLocal(x,y,target,this);
}
}
this.dispose = function(a,b,disposing) {
this.dispatchEvent("removed");
this.removeAllEventListeners();
if (this.parent) this.parent.removeChild(this);
}
}
zim.extend(zim.MovieClip, createjs.MovieClip, ["clone","localToLocal","localToGlobal","globalToLocal"], "cjsMovieClip", false);
zimify(zim.MovieClip.prototype);
//-50.9
/*--
zim.SVGContainer = function(svg, splitTypes, geometric, showControls, interactive, style, group, inherit)
SVGContainer
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Parses SVG and adds items to a ZIM Container.
Items are created as ZIM Shapes: Circle, Rectangle, Blob, Squiggle.
If geometric is true then Circle and Rectangle are used otherwise Blob is used.
Items can be accessed using svgcontainer.getChildAt(0), etc.
See: https://zimjs.com/svg/
See: https://zimjs.com/explore/svgcontainer.html
An SVG path string can be passed directly to a Squiggle or Blob points parameter
and so avoiding the SVGContainer - see ZIM Squiggle and Blob
WARNING: this should be considered experimental
The idea is that paths from SVG can be made editable in ZIM
or animation, dragging, or Label along paths can be accommodated
As such, not all SVG features will work - no CSS, Text, Gradients, DropShadows, etc.
It is possible that these will be added at some point
See also the ZIM svgToBitmap() function under META to get an exact image of the SVG
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var svgContainer = new SVGContainer(frame.asset("sample.svg")).addTo();
// OR
var svg = ``;
var svgContainer = new SVGContainer(svg).center();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
svg - an SVG file loaded into a frame.asset() or SVG text
splitTypes - (default false) - set to true to split different types of paths into separate objects
geometric - (default true) - set to false to load Rectangle and Circle objects as Blob objects
showControls - (default true) set to false to start with controls not showing
interactive - (default true) set to false to turn off controls, move, toggle, select, edit - leaving just the shapes
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
processPath(path) - path is an SVG path string - returns a ZIM Blob or Squiggle points array
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
svg - a reference to the SVG text
type - holds the class name as a String
** bounds must be set first for these to work
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
depth - for ZIM VR - the depth used to shift left and right channel and for parallax in VR - also see dep() ZIM Display method
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+50.95
zim.SVGContainer = function(svg, splitTypes, geometric, showControls, interactive, style, group, inherit) {
var sig = "svg, splitTypes, geometric, showControls, interactive, style, group, inherit";
var duo; if (duo = zob(zim.SVGContainer, arguments, sig, this)) return duo;
z_d("50.95");
this.group = group;
var DS = style===false?{}:zim.getStyle("SVGContainer", this.group, inherit);
var that = this;
var startPosition = new zim.Point(0,0); // the x,y of the last shape
var aCommand=[]; //kv adjust logic
if (zot(splitTypes)) splitTypes = false;
if (zot(geometric)) geometric = true;
if (!zot(svg)) {
if (!zot(svg.draggable)) {
var parser = new DOMParser();
var svg = !svg.innerHTML?svg:parser.parseFromString(svg.innerHTML,"text/xml");
var list = svg.getElementsByTagName("svg");
var tag = this.svg = list?svg.getElementsByTagName("svg")[0]:null;
} else {
if (!svg.getAttribute) {
var parser = new DOMParser();
svg = parser.parseFromString(svg, "image/svg+xml").documentElement;
}
var tag = this.svg = svg;
}
var w, h;
if (!zot(tag)){
var w = tag.getAttribute("width");
var h = tag.getAttribute("height");
}
if (w) w = Number(w.trim());
if (h) h = Number(h.trim());
this.zimContainer_constructor(w, h);
this.type = "SVGContainer";
if (zot(tag)) return;
var defaultFill = zim.black, generalFill = zim.black;
var defaultStroke =zim. black, generalStroke = zim.black;
var defaultStrokeSize = 2, generalStrokeSize = 2;
var defaultAlpha = 1, generalAlpha = 1;
var defaultStrokeAlpha = 1, generalStrokeAlpha = 1;
var currentTransform;
function processTag(tag) {
zim.loop(tag, function (t) {
var tn = t.tagName.toLowerCase();
if (tn == "path") processPath(t);
if (tn == "circle") processShape("circle", t);
if (tn == "rect") processShape("rect", t);
if (tn == "ellipse") processShape("ellipse", t);
if (tn == "line") processShape("line", t);
if (tn == "polygon") processShape("polygon", t);
if (tn == "polyline") processShape("polyline", t);
if (tn == "g") {
// styles can be overwritten by parameters in the general tag
// so find styles first
var style = t.getAttribute("style");
var f,s,ss,a,aa;
if (style) {
var styles = processStyle(style);
f = styles[0];
s = styles[1];
ss = styles[2];
a = styles[3];
aa = styles[4];
}
// then overwrite styles with any attribute values
currentTransform = t.getAttribute("transform");
generalFill = t.getAttribute("fill")?t.getAttribute("fill"):!zot(f)?f:defaultFill;
generalStroke = t.getAttribute("stroke")?t.getAttribute("stroke"):!zot(s)?s:defaultStroke;
generalStrokeSize = t.getAttribute("stroke-width")?t.getAttribute("stroke-width"):!zot(ss)?ss:defaultStrokeSize;
generalAlpha = t.getAttribute("fill-opacity")?t.getAttribute("fill-opacity"):!zot(a)?a:defaultAlpha;
generalStrokeAlpha = t.getAttribute("stroke-opacity")?t.getAttribute("stroke-opacity"):!zot(aa)?aa:defaultStrokeAlpha;
}
// general settings can wrap any number of tags - the tags are processed here:
processTag(t.children);
// after this nest of tags are processed, clear the general settings
if (t.tagName.toLowerCase() == "g") {
generalFill = defaultFill;
generalStroke = defaultStroke;
generalStrokeSize = defaultStrokeSize;
generalAlpha = defaultAlpha;
generalStrokeAlpha = defaultStrokeAlpha;
currentTransform = null;
}
})
}
var process = svg.getElementsByTagName("svg");
if (process.length == 0) process = [svg];
function processStyle(style) {
var st = style.split(";"); //kv note: there si bug when style contains ; at the end of the string
var f,s,ss,a,aa;
loop(st, function (sty) {
var sty = sty.replace(/,/g,"");
var styl = sty.split(":");
var prop = styl[0].trim().toLowerCase();
var val = styl[1].trim().toLowerCase().replace("px", "");
if (prop=="fill") f = val;
if (prop=="stroke") s = val;
if (prop=="stroke-width") ss = val;
if (prop=="opacity") a = val, aa = val;
if (prop=="fill-opacity") a = val;
if (prop=="stroke-opacity") aa = val;
});
return [f,s,ss,a,aa];
}
function processShape(type, tag) {
var shape;
var g = processGeneral(tag); // want ES6
var f = g[0], s = g[1], ss = g[2], a = g[3], aa = g[4], x = g[5], y = g[6];
if (type == "circle") {
var r = Number(tag.getAttribute("r").trim());
var d = r*.5523;
if (geometric) shape = new zim.Circle(Number(tag.getAttribute("r")), f, s, ss);
else shape = new zim.Blob(f, s, ss, 4, r, d, "mirror", null, showControls, null, null, null, null, null, null, null, null, null, null, interactive);
} else if (type == "rect") {
if (geometric) shape = new zim.Rectangle(Number(tag.getAttribute("width")), Number(tag.getAttribute("height")), f, s, ss, Number(tag.getAttribute("rx")));
else {
var w = Number(tag.getAttribute("width"));
var h = Number(tag.getAttribute("height"));
var rx = Number(tag.getAttribute("rx"));
var ry = Number(tag.getAttribute("ry"));
if (rx && ry) {
var dx = rx*.5523;
var dy = ry*.5523;
shape = new zim.Blob(f, s, ss, [
[rx,0,0,0,-dx,0,0,0,"free"],[w-rx,0,0,0,0,0,dx,0,"free"],
[w,ry,0,0,0,-dy,0,0,"free"],[w,h-ry,0,0,0,0,0,dy,"free"],
[w-rx,h,0,0,dx,0,0,0,"free"],[rx,h,0,0,0,0,-dx,0,"free"],
[0,h-ry,0,0,0,dy,0,0,"free"],[0,ry,0,0,0,0,0,-dy,"free"]], null, null, null, null, showControls, null, null, null, null, null, null, null, null, null, null, interactive);
} else {
shape = new zim.Blob(f, s, ss, [[0,0],[w,0],[w,h],[0,h]], null, null, null, null, showControls, null, null, null, null, null, null, null, null, null, null, interactive);
}
}
} else if (type == "line") {
shape = new zim.Squiggle(s, ss, [[Number(tag.getAttribute("x1")), Number(tag.getAttribute("y1"))],[Number(tag.getAttribute("x2")), Number(tag.getAttribute("y2"))]], null, null, null, null, showControls, null, null, null, null, null, null, null, null, null, null, interactive);
} else if (type == "polygon" || type == "polyline") {
var p = tag.getAttribute("points");
p = p.replace(/-/g, " -");
p = p.replace(/\s+/g, " ");
var points = [];
if (p.indexOf(",") != -1) {
loop(p.split(" "), function (point) {
var pp = point.split(",");
points.push([Number(pp[0].trim()), Number(pp[1].trim())]);
});
} else {
var lastP;
loop(p.split(" "), function (point, i) {
if ((i+1)%2==0) points.push([lastP, point.trim()]);
lastP = point.trim();
});
}
if (type=="polygon") shape = new Blob(f, s, ss, points);
else shape = new zim.Squiggle(s, ss, points, null, null, null, null, showControls, null, null, null, null, null, null, null, null, null, null, interactive);
} else if (type == "ellipse") {
shape = new zim.Blob(f, s, ss, ellipse(0, 0, Number(tag.getAttribute("rx")), Number(tag.getAttribute("ry"))), null, null, null, null, showControls, null, null, null, null, null, null, null, null, null, null, interactive);
}
shape.loc(x,y,that);
var transform = tag.getAttribute("transform");
if (transform || currentTransform) processTransform(shape, transform || currentTransform);
if (interactive && (shape.type == "Rectangle" || shape.type=="Circle")) shape.transform({showReg:false, visible:showControls})
}
function processTransform(shape, transform) {
var tr = transform.split(")");
// apply all transforms in the order given
loop(tr, function (tra) {
if (tra=="") return;
var tran = tra.trim().split("(");
var prop = tran[0].trim().toLowerCase();
var val = tran[1].trim().toLowerCase().replace("px", "").replace("deg", "");
if (prop=="translate") {
var m = val.split(",");
shape.mov(Number(m[0].trim()), m[1]?Number(m[1].trim()):0);
}
if (prop=="scale"){
var s = val.split(",");
if (shape.type=="Blob" || shape.type=="Squiggle") {
if (s.length == 1) shape.transformPoints("scale", Number(s[0].trim()))
else if (s.length == 2) {
shape.transformPoints("scaleX", Number(s[0].trim()));
shape.transformPoints("scaleY", Number(s[1].trim()));
}
} else {
if (s.length == 1) shape.sca(Number(s[0].trim()))
else if (s.length == 2) {
shape.sca(Number(s[0].trim()), Number(s[1].trim()));
}
}
}
if (prop=="rotate") {
var r = val.split(",");
// if (shape.type=="Blob" || shape.type=="Squiggle") {
// rotation is a different way for SVG and transform() - too bad
// it rotates around 0,0 unless a different point is chosen
// so shape.transformPoints which is a registration point system
// is unlikely to work - and too complex to add rotate around a given point
// so we will use zim rot() to which we have added rotating around a different point
// but this will rotate the little box handles
// maybe look into keeping those parallel in the blob and squiggle - no matter what the rotation
// if (r.length == 1) shape.transformPoints("rotation", Number(r[0].trim()))
if (r.length == 1) r.push(0,0);
else if (r.length == 2) r.push(0);
shape.rot(Number(r[0].trim()), Number(r[1].trim()), Number(r[2].trim()));
}
if (prop=="skewX") shape.skewX = val;
if (prop=="skewY") shape.skewY = val;
});
}
// beatgammit on StackOverflow
function ellipse(x, y, xDis, yDis) {
var kappa = 0.5522848, // 4 * ((√(2) - 1) / 3)
ox = xDis * kappa, // control point offset horizontal
oy = yDis * kappa, // control point offset vertical
xe = x + xDis, // x-end
ye = y + yDis; // y-end
var points = [ // modified by Dan Zen to relative
[x - xDis, y, 0, 0, x, ye+oy-yDis, x, y-oy, "mirror"],
[x, y - yDis, 0, 0, x-ox, y, xe+ox-xDis, y, "mirror"],
[xe, y, 0, 0, x, y-oy, x + ox-ox, ye+oy-yDis, "mirror"],
[x, ye, 0, 0, xe-xDis+ox, y, x-ox, y, "mirror"]
];
return points;
}
processTag(process);
}
function processGeneral(tag) {
// any styles on the tag overwrites general styles or attributes
var f,s,ss,a,aa;
var style = tag.getAttribute("style");
if (style) {
var styles = processStyle(style);
f = styles[0];
s = styles[1];
ss = styles[2];
a = styles[3];
aa = styles[4];
}
// kv comments: need to apply string cleansing, application bugs when there is a semi colon character used in tags.
// get rid of semi colon,
// any attributes on the tag overwrites styles or general
f = tag.getAttribute("fill")?tag.getAttribute("fill"):!zot(f)?f:generalFill;
s = tag.getAttribute("stroke")?tag.getAttribute("stroke"):!zot(s)?s:generalStroke;
ss = tag.getAttribute("stroke-width")?tag.getAttribute("stroke-width"):!zot(ss)?ss:generalStrokeSize;
a = tag.getAttribute("fill-opacity")?tag.getAttribute("fill-opacity"):!zot(a)?a:generalAlpha;
aa = tag.getAttribute("stroke-opacity")?tag.getAttribute("stroke-opacity"):!zot(aa)?aa:generalStrokeAlpha;
var x = tag.getAttribute("x")?tag.getAttribute("x"):0;
x = tag.getAttribute("cx")?tag.getAttribute("cx"):x;
var y = tag.getAttribute("y")?tag.getAttribute("y"):0;
y = tag.getAttribute("cy")?tag.getAttribute("cy"):y;
if (!zot(a) && !zot(f)) f = zim.convertColor(f, "rgba", Number(a));
if (!zot(aa) && !zot(s)) s = zim.convertColor(s, "rgba", Number(aa));
return [f,s,Number(ss),Number(a),Number(aa),Number(x),Number(y)];
}
function processPath (path, make) {
if (zot(make)) make = true;
var commands = ["M","m","L","l","H","h","V","v","C","c","S","s","Q","q","T","t","A","a","z","Z"];
var commandsRelative = ["m","l","h","v","c","s","q","t","a","z"];
var position = new zim.Point(0,0); // the current position - relative places based on this
if (zot(path.getAttribute)) {
var d = path;
} else {
var id = path.getAttribute("id");
var d = path.getAttribute("d");
}
// m251.85 119.04c7.85 10.45-9.81
d = d.replace(/,/g ," ");
d = d.replace(/([a-zA-Z])/g, " $1 ");
d = d.replace(/-/g, " -");
d = d.replace(/\s+/g, " ");
if (make) {
var g = processGeneral(path); // want ES6
var f = g[0]; var s = g[1]; var ss = g[2]; var a = g[3]; var aa = g[4];
}
var shape; //kv adjust logic
var aNumber; //kv adjust logic
//var points = [[0,0]]; //kv adjust logic
var points = []; //kv adjust logic
var lastTempPoint = [0,0]; //kv adjust logic
var line = new zim.Point(0,0);
var quad = new zim.Point(0,0,0,0);
var cube = new zim.Point(0,0,0,0,0,0);
var arc = new zim.Point(0,0,0,0,0,0,0);
//kv var data = d.split(" "); //kv adjust logic
var dataOrigin = d.split(" "); //kv adjust logic
var data = dataOrigin.slice(1,dataOrigin.length); //kv adjust logic
var aCommand = []; //kv adjust logic
var missingCommand = false; //not used yet //kv adjust logic
var lastCommand = ""; //kv adjust label
var previousCommand = ""; //not used yet //kv adjust logic
var adding = false;
var what;
var type = "squiggle";
var dataType = null;
//kv loop(data, function (command) { //kv adjust logic
zim.loop(data, function (command,i) {
//kv adjust logic
if (i==0) {startPosition.x = 0; startPosition.y=0;lastTempPoint = [0,0];lastCommand = "";previousCommand = ""};
if (commands.indexOf(command) == -1) {
if (what == "lxo") {what="lx"; aCommand.push("l");missingCommand=true}; //kv adjust logic
if (what == "lyo") {what="ly"; missingCommand=true}; //kv adjust logic
if (what == "Lxo") {what="Lx"; aCommand.push("L");missingCommand=true}; //kv adjust logic
if (what == "Lyo") {what="Ly"; missingCommand=true}; //kv adjust logic
aNumber = Number(command); //kv adjust logic
aNumber = Math.round(aNumber * 100) / 100; //kv adjust logic
// position
if (what == "X") {
startPosition.x = aNumber;
what = "Y";
} else if (what == "Y") {
startPosition.y = aNumber;
//kv what = "Lx"; // in case no letters come next //kv adjust logic
what = "Lxo"; // in case no letters come next //kv adjust logic
points.push([startPosition.x, startPosition.y]); //kv adjust logic
// what = null;
} else if (what == "x") {
//if (points.length > 1) {
// startPosition.x = points[points.length-1][0]; //kv adjust logic
// startPosition.y = points[points.length-1][1] //kv adjust logic
//} else {
// startPosition.x = lastTempPoint[0]; //kv adjust logic
// startPosition.y = lastTempPoint[1] //kv adjust logic
//};
startPosition.x = startPosition.x+aNumber;
what = "y";
} else if (what == "y") {
startPosition.y = startPosition.y+aNumber;
what = "lxo"; //kv adjust logic
//kv what = "lx"; // in case no letters come next //kv adjust logic
points.push([startPosition.x, startPosition.y]); //kv adjust logic
// what = null;
}
// left, right, top or bottom
if (what == "H" || what == "h") {
position.x = points[points.length-1][0]; //kv adjust logic
position.y = points[points.length-1][1]; //kv adjust logic
position.x = position.x + (what=="h"?aNumber:aNumber-startPosition.x);
points.push([position.x, position.y]);
what = "Lx"
} else if (what == "V" || what == "v") {
position.x = points[points.length-1][0]; //kv adjust logic
position.y = points[points.length-1][1]; //kv adjust logic
position.y = position.y + (what=="v"?aNumber:aNumber-startPosition.y);
points.push([position.x, position.y]);
what = "lx"
}
// line
if (what == "Lx") {
//kv line.x = aNumber-startPosition.x; //kv adjust logic
line.x = aNumber; //kv adjust logic
what = "Ly";
} else if (what == "Ly") {
//kv line.y = aNumber-startPosition.y; //kv adjust logic
line.y = aNumber; //kv adjust logic
position.x = line.x;
position.y = line.y;
points.push([position.x, position.y]);
what = "Lx"
} else if (what == "lx") {
if (aCommand.length > 0) { //kv adjust logic
if (position.x != 0 && position.y != 0 ) {
startPosition.x = position.x;
startPosition.y = position.y
}
else {
startPosition.x = position.x + startPosition.x; //kv adjust logic
startPosition.y = position.y + startPosition.y; //kv adjust logic
//startPosition.x = position.x + lastTempPoint[0]; //kv adjust logic
//startPosition.y = position.y + lastTempPoint[1]; //kv adjust logic
}
}; //kv adjust logic
line.x = startPosition.x + aNumber; //kv adjust logic
//kv line.x = line.x + aNumber; //kv adjust logic
if (missingCommand) {what="lyo"} else //kv adjust logic
what = "ly";
} else if (what == "ly") {
line.y = startPosition.y + aNumber; //kv adjust logic
//line.y = line.y + aNumber; //kv adjust logic
position.x = line.x;
position.y = line.y;
points.push([position.x, position.y]);
what = "lx";
}
// Quadratic
if (what == "qx" || what == "Qx") {
if (points.length > 0) { //kv adjust logic
startPosition.x = points[points.length-1][0]; //kv adjust logic
startPosition.y = points[points.length-1][1] //kv adjust logic
} else { //kv adjust logic
startPosition.x = 0; //kv adjust logic
startPosition.y = 0 //kv adjust logic
}; //kv adjust logic
//kv quad.x = what=="qx"?position.x+aNumber:aNumber-startPosition.x;
quad.x = what=="qx"?startPosition.x+aNumber:aNumber; //kv adjust logic
what = what=="qx"?"qy":"Qy";
} else if (what == "qy" || what == "Qy") {
//kv quad.y = what=="qy"?position.y+aNumber:aNumber-startPosition.y;
quad.y = what=="qy"?startPosition.y+aNumber:aNumber; //kv adjust logic
what = what=="qy"?"qz":"Qz";
if (adding) {
adding = false;
var lastPoint = points[points.length-1];
lastPoint[6] = -lastPoint[4];
lastPoint[7] = -lastPoint[5];
lastPoint[8] = "mirror";
position.x = quad.x;
position.y = quad.y;
points[points.length] = [
position.x, position.y,
0, 0,
-lastPoint[6], lastPoint[7],
0,0,
"free"
];
what = what=="qy"?"qx":"Qx";
}
} else if (what == "qz" || what == "Qz") {
//kv quad.z = what=="qz"?position.x+aNumber:aNumber-startPosition.x;
quad.z = what=="qz"?startPosition.x+aNumber:aNumber; //kv adjust logic
what = what=="qz"?"qq":"Qq";
} else if (what == "qq" || what == "Qq") {
//kv quad.w = what=="qq"?position.y+aNumber:aNumber-startPosition.y;
quad.w = what=="qq"?startPosition.y+aNumber:aNumber; //kv adjust logic
var lastPoint = points[points.length-1];
position.x = lastPoint[0]; //kv adjust logic
position.y = lastPoint[1]; //kv adjust logic
if (points.length == 1) { //kv adust logic
lastPoint[2] = 0; lastPoint[3] = 0; lastPoint[4] = 0; lastPoint[5] = 0; //kv adjust logic //kv debug
lastPoint[6] = 2/3 *(quad.x - position.x); // relative needs position and absolute does not it
lastPoint[7] = 2/3 *(quad.y - position.y);
lastPoint[8] = "free"
} //kv adjust logic
else { //kv adjust logic
points[points.length] = [ //kv adjust logic
position.x, position.y, //kv adjsut logic
0, 0, 0, 0, //kv adjust logic
2/3*(quad.x-position.x), //kv adjust logic
2/3*(quad.y-position.y), //kv adjust logic
"free" //kv adjust logic
] //kv adjust logic
}; //kv adjust logic
position.x = quad.z; // assign this point's position - fix this and apply throughout...
position.y = quad.w;
points[points.length] = [
position.x, position.y,
0, 0,
// relative needs - startPosition and absolute does not
2/3*(quad.x-position.x), 2/3*(quad.y-position.y),
0,0,
"free"
];
what = what=="qq"?"qx":"Qx"
};
// Cubic
if (what == "cx" || what == "Cx") {
if (points.length > 0) { //kv adjust logic
startPosition.x = points[points.length-1][0]; //kv adjust logic
startPosition.y = points[points.length-1][1] //kv adjust logic
} else { //kv adjust logic
startPosition.x = 0; //kv adjust logic
startPosition.y = 0 //kv adjust logic
}; //kv adjust logic
//kv cube.x = what=="cx"?position.x+aNumber:aNumber-startPosition.x;
cube.x = what=="cx"?startPosition.x+aNumber:aNumber; //kv adjust logic
what = what=="cx"?"cy":"Cy";
} else if (what == "cy" || what == "Cy") { // y Control Point 1
//kv cube.y = what=="cy"?position.y+aNumber:aNumber-startPosition.y;
cube.y = what=="cy"?startPosition.y+aNumber:aNumber; //kv adjust logic
what = what=="cy"?"cz":"Cz";
} else if (what == "cz" || what == "Cz") { // x Control Point 2
//kv cube.z = what=="cz"?position.x+aNumber:aNumber-startPosition.x;
cube.z = what=="cz"?startPosition.x+aNumber:aNumber; //kv adjust logic
what = what=="cz"?"cq":"Cq";
} else if (what == "cq" || what == "Cq") { // y Control Point 2
//kv cube.q = what=="cq"?position.y+aNumber:aNumber-startPosition.y;
cube.q = what=="cq"?startPosition.y+aNumber:aNumber; //kv adjust logic
what = what=="cq"?"cr":"Cr";
if (adding) {
if (lastCommand=="s") {previousCommand = "s"} else {previousCommand = "S"};
//kv adding = false;
//kv update previous point
var lastPoint = points[points.length-1];
lastPoint[2] = 0; //kv adjust logic
lastPoint[3] = 0; //kv adjust logic
if(zot(lastPoint[4])) {lastPoint[4] =0}; //kv adjust logic
if(zot(lastPoint[5])) {lastPoint[5] =0}; //kv adjust logic
lastPoint[6] = -lastPoint[4];
lastPoint[7] = -lastPoint[5];
// lastPoint[6] = - (cube.x-cube.z); //kv adjust logic
// lastPoint[7] = - (cube.y-cube.q); //kv adjust logic
lastPoint[8] = "mirror";
//kv create very lastPoint
position.x = cube.z;
position.y = cube.q;
points[points.length] = [
position.x, position.y,
0, 0,
cube.x-position.x, cube.y-position.y,
0,0,
"free"
];
//kv what = what=="cq"?"cx":"Cx";
what = what=="cr"?"cx":"Cx" //kv adjust logic
}
} else if (what == "cr" || what == "Cr") {
//kv cube.r = what=="cr"?position.x+aNumber:aNumber-startPosition.x;
cube.r = what=="cr"?startPosition.x+aNumber:aNumber; //kv adjust logic
what = what=="cr"?"cs":"Cs";
} else if (what == "cs" || what == "Cs") { // y 2nd Point
//kv cube.s = what=="cs"?position.y+aNumber:aNumber-startPosition.y;
cube.s = what=="cs"?startPosition.y+aNumber:aNumber; //kv adjust logic
//points.push([cube.r, cube.s]); //kv adjust logic
//[controlX, controlY, circleX, circleY, rect1X, rect1Y, rect2X, rect2Y, controlType], //kv debug
var lastPoint = points[points.length-1];
if (points.length == 1) {lastPoint[2] = 0; lastPoint[3] = 0; lastPoint[4] = 0; lastPoint[5] = 0}; //kv adjust logic
lastPoint[6] = cube.x-lastPoint[0];
lastPoint[7] = cube.y-lastPoint[1];
lastPoint[8] = "free";
position.x = cube.r;
position.y = cube.s;
points[points.length] = [
position.x, position.y,
0, 0,
cube.z-position.x, cube.q-position.y,
0,0,
"free"
];
what = what=="cs"?"cx":"Cx";
}
// // Arc - TODO - equation does not seem to work
// // https://github.com/colinmeinke/svg-arc-to-cubic-bezier/issues/7
// // rx ry x-axis-rotation large-arc-flag sweep-flag x y
// if (what == "ax" || what == "Ax") {
// arc.x = aNumber; // radius x
// what = what=="ax"?"ay":"Ay";
// } else if (what == "ay" || what == "Ay") {
// arc.y = aNumber; // radius y
// what = what=="ay"?"az":"Az";
// } else if (what == "az" || what == "Az") {
// arc.z = aNumber; // x-axis-rotation
// what = what=="az"?"aq":"Aq";
// } else if (what == "aq" || what == "Aq") {
// arc.q = aNumber; // large-arc-flag
// what = what=="aq"?"ar":"Ar";
// } else if (what == "ar" || what == "Ar") {
// arc.r = aNumber; // sweep-flag
// what = what=="ar"?"as":"As";
// } else if (what == "as" || what == "As") {
// arc.s = what=="as"?position.x+aNumber:aNumber-startPosition.x;
// //zog(arc.s)
// what = what=="as"?"at":"At";
// } else if (what == "at" || what == "At") {
// arc.t = what=="at"?position.y+aNumber:aNumber-startPosition.y;
// //zog(arc.t)
// // rx ry x-axis-rotation large-arc-flag sweep-flag x y
//
// zta(arc)
// var curves = arcToBezier({
// px: position.x,
// py: position.y,
// cx: arc.s,
// cy: arc.t,
// rx: arc.x,
// ry: arc.y,
// xAxisRotation: arc.z,
// largeArcFlag: arc.q,
// sweepFlag: arc.r,
// });
//
// //zta(curves)
//
// loop(curves, function (curve) {
// lastPoint = points[points.length-1];
// lastPoint[6] = curve.x1-position.x;
// lastPoint[7] = curve.y1-position.y;
// lastPoint[8] = "free";
// //zog(curve.x, curve.y)
// position.x = curve.x;
// position.y = curve.y;
// points[points.length] = [
// position.x, position.y,
// 0, 0,
// curve.x2-position.x, curve.y2-position.y,
// 0,0,
// "free"
// ];
// });
// what = what=="at"?"ax":"Ax";
// }
}
else {
aCommand.push(command); // kv adjust logic
// Commands
if (command != "s") {
adding = false;
} // kv adjust logic
if (aCommand.length > 1) { // kv adjust logic
// if (aCommand[aCommand.length-2] != command) {
if (command=="M" || command=="m") {
makeShape(aCommand);
if (command=="M") {startPosition.x = 0; startPosition.y=0}
else {
startPosition.x = points[points.length-1][0]; startPosition.y=points[points.length-1][1];
};
points = [];
aCommand = [];
aCommand.push(command)
}
}; // kv adjust logic
if (command=="M") {
what = "X";
} else if (command=="m") {
what = "x";
} else if (command=="L") {
what = "Lx";
if (splitTypes && dataType && (dataType != "l")) makeShape(aCommand);
dataType = "l";
} else if (command=="l") {
what = "lx";
if (splitTypes && dataType && (dataType != "l")) makeShape(aCommand);
dataType = "l";
} else if (command=="H") {
what = "H";
if (splitTypes && dataType && (dataType != "l")) makeShape(aCommand);
dataType = "l";
} else if (command=="h") {
what = "h";
if (splitTypes && dataType && (dataType != "l")) makeShape(aCommand);
dataType = "l";
} else if (command=="V") {
what = "V";
if (splitTypes && dataType && (dataType != "l")) makeShape(aCommand);
dataType = "l";
} else if (command=="v") {
what = "v";
if (splitTypes && dataType && (dataType != "l")) makeShape(aCommand);
dataType = "l";
} else if (command=="C") {
what = "Cx";
if (splitTypes && dataType && (dataType != "c")) makeShape(aCommand);
dataType = "c";
} else if (command=="c") {
what = "cx";
if (splitTypes && dataType && (dataType != "c")) makeShape(aCommand);
dataType = "c";
} else if (command=="S") {
adding = true;
what = "Cx";
if (splitTypes && dataType && (dataType != "c")) makeShape(aCommand);
dataType = "c";
} else if (command=="s") {
adding = true;
what = "cx";
if (splitTypes && dataType && (dataType != "c")) makeShape(aCommand);
dataType = "c";
} else if (command=="Q") {
what = "Qx";
if (splitTypes && dataType && (dataType != "q")) makeShape(aCommand);
dataType = "q";
} else if (command=="q") {
what = "qx";
if (splitTypes && dataType && (dataType != "q")) makeShape(aCommand);
dataType = "q";
} else if (command=="T") {
adding = true;
what = "Qx";
if (splitTypes && dataType && (dataType != "q")) makeShape(aCommand);
dataType = "q";
} else if (command=="t") {
adding = true;
what = "qx";
if (splitTypes && dataType && (dataType != "q")) makeShape(aCommand);
dataType = "q";
} else if (command=="A") {
type = null;
// what = "Ax";
// if (splitTypes && dataType && (dataType != "a")) makeShape();
// dataType = "a";
// } else if (command=="a") {
// what = "ax";
// if (splitTypes && dataType && (dataType != "a")) makeShape();
// dataType = "a";
} else if (command=="z" || command=="Z") {
type = "blob";
}
} // end of Command process
}); // end of data loop
function makeShape(myCommand, interest) {
var myCommand;
//var shape; //kv adjust logic
lastCommand = aCommand[aCommand.length-1]; //kv adjust logic
if (points.length >= 2)
// M 100 350 l 150 -300
if (lastCommand == "z" || lastCommand == "Z") {type = "blob"}; //kv adjust logic
//if (zot(shape)) { //kv adjust logic
if (type == "squiggle") shape = new zim.Squiggle(s, ss, points, null, null, null, null, showControls, null, null, null, null, null, null, null, null, null, null, interactive);
else shape = new zim.Blob(f, s, ss, points, null, null, null, null, showControls, null, null, null, null, null, null, null, null, null, null, interactive);
shape.loc(0,0,that); //kv adjust logic
//} else { //kv adjust logic
// var dataPointsArray = []; //kv adjust logic
// dataPointsArray = shape.recordPoints().concat(points); //kv adjust logic
// //shape.removeFrom(); //kv adjust logic
// if (type == "squiggle") shape = new Squiggle(s, ss, dataPointsArray) //kv adjust logic
// else shape = new Blob(f, s, ss, dataPointsArray) //kv adjust logic
//};
//kv shape.loc(startPosition.x, startPosition.y, that); //kv adjust logic
//kv startPosition.x = startPosition.x + position.x; //kv adjust logic
//kv startPosition.y = startPosition.y + position.y; //kv adjust logic
lastCommand = aCommand[aCommand.length-1]; //kv adjust logic
previousCommand = aCommand[aCommand.length-2]; //kv adjust logic
if (commandsRelative.indexOf(lastCommand) >= 0) {
//if (aCommand[aCommand.length-1] == "m") { //kv adjust logic
lastTempPoint[0] = points[points.length-1][0]; lastTempPoint[1] = points[points.length-1][1]; //kv adjust logic
startPosition.x = points[points.length-1][0]; startPosition.y = points[points.length-1][1]; //kv adjust logic
points = []; // LATEST CHANGES
points.push([lastTempPoint[0], lastTempPoint[1]]); //kv adjust logic
} else {lastTempPoint = [0,0]; points = [[0,0]]};
aCommand = []; //kv adjust logic
if (lastCommand != "z" && lastCommand != "Z") aCommand.push(lastCommand); //kv adjust logic
position.x = 0;
position.y = 0;
//kv points = [[0,0]];
var transform = path.getAttribute("transform");
if (transform || currentTransform) processTransform(shape, transform || currentTransform);
};
if (make) makeShape();
return points;
} // end process path
that.processPath = function(path) {
return processPath(path,false);
}
if (style!==false) zimStyleTransforms(this, DS); // global function - would have put on DisplayObject if had access to it
this.clone = function() {
return that.cloneProps(new zim.SVGContainer(svg, splitTypes, geometric, showControls, interactive, style, this.group, inherit));
}
}
zim.extend (zim.SVGContainer, zim.Container, "clone", "zimContainer", false);
//-50.95
// SUBSECTION ZIM SHAPES
/*--
zim.Circle = function(radius, color, borderColor, borderWidth, dashed, percent, percentClose, strokeObj, style, group, inherit)
Circle
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Makes a circle shape inside a container.
The registration and origin will be the center.
NOTE: mouseChildren is turned to false for all zim Shape containers.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var circle = new Circle(50, "red");
circle.center(stage);
// or with 10 pixel grey stroke
var circle = new Circle(50, "red", "#666", 10);
// fill the circle with a radial gradient fill
circle.colorCommand.radialGradient([yellow,green], [0, .7], 0, 0, 20, 0, 0, 50);
// make a half circle - or any percent of a circle
var semi = new Circle({radius:200, color:pink, percent:50}).center();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports VEE - parameters marked with ZIM VEE mean a zim Pick() object or Pick Literal can be passed
Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
radius - |ZIM VEE| (default 50) the radius (from the center to the edge or half the diameter) ;-)
color - |ZIM VEE| (default "black") the fill color as any CSS color including "rgba()" for alpha fill (set a to 0 for tranparent fill)
borderColor - |ZIM VEE| (default null) the stroke color
borderWidth - |ZIM VEE| (default 1 if stroke is set) the size of the stroke in pixels
dashed - (default false) set to true for dashed border (if borderWidth or borderColor set)
percent - (default 100) set to a percentage of a circle (arc) - registration stays at radius center, bounds shrink to arc
percentClose - (default true) set to false to not close the border of a circle with percent set
strokeObj - (default {caps:"butt", joints:"miter", miterLimit:10, ignoreScale:false}) set to adjust stroke properties
// note, not all applicable to a Circle - perhaps just ignoreScale...
caps options: "butt", "round", "square" or 0,1,2
joints options: "miter", "round", "bevel" or 0,1,2
miterLimit is the ration at which the mitered joint will be clipped
ignoreScale set to true will draw the specified line thickness regardless of object scale
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
linearGradient([colors],[ratios], x0,y0, x1,y1) - shortcut to colorCommand linearGradient method (see properties below)
radialGradient([colors],[ratios], x0,y0,radius0, x1,y1,radius1) - shortcut to colorCommand radialGradient method (see properties below)
setColorRange(color1, color2) - set a color range for shape - used by colorRange property - returns obj for chaining
if one color is used, the current color is used and color1 is the second color in the range
cache(see Container docs for parameter description) - overrides CreateJS cache() and returns object for chaining
Leave parameters blank to cache bounds of shape (plus outer edge of border if borderWidth > 0)
hasProp(property as String) - returns true if property exists on object else returns false
clone(exact) - makes a copy of the shape
exact (default false) ZIM VEE (Pick) values are active in clones unless exact is set to true
For instance, if the object's color is [blue, green]
then its clone might be blue or green - which could be different than the original
If exact is set to true then the clone will be the color of the original object
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
shape - gives access to the circle shape
color - get and set the fill color
colorRange - if setColorRange() is used, the colorRange is a ratio (0-1) between the colors
setting the colorRange will change the color property of the shape
for instance, shape.setColorRange(blue, pink) then shape.colorRange = .5
will set the color of the shape to half way between blue and pink
shape.animate({color:red}, 1000); is a shortcut to animate the colorRange
shape.wiggle("colorRange", .5, .2, .5, 1000, 5000) will wiggle the colorRange
colorCommand - access to the CreateJS fill command for bitmap, linearGradient and radialGradient fills
eg. var shape = new Circle(20);
// colors,ratios, x0,y0,radius0, x1,y1,radius1
// purple on outside with pink highlight right top corner
shape.colorCommand.radialGradient([purple,pink],[0,.8], 0,0,20, 5,-8,0);
See: https://www.createjs.com/docs/easeljs/classes/Graphics.Fill.html
borderColor - get and set the stroke color
borderColorCommand - access to the CreateJS stroke command for bitmap, linearGradient and radialGradient strokes
See: https://www.createjs.com/docs/easeljs/classes/Graphics.Stroke.html
borderWidth - get and set the stroke size in pixels
borderWidthCommand - access to the CreateJS stroke style command (width, caps, joints, miter, ignoreScale)
See: https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeStyle.html
borderDashedCommand - access to the CreateJS stroke dashed command (segments, offset)
see https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeDash.html
radius - gets or sets the radius.
The radius is independent of scaling and can be different than the width/2
Setting the radius redraws the circle but any current scaling is kept
** setting widths, heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
mouseChildren - set to false so you do not drag the shape inside the circle
if you nest things inside and want to drag them, will want to set to true
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+51
zim.Circle = function(radius, color, borderColor, borderWidth, dashed, percent, percentClose, strokeObj, style, group, inherit) {
var sig = "radius, color, borderColor, borderWidth, dashed, percent, percentClose, strokeObj, style, group, inherit";
var duo; if (duo = zob(zim.Circle, arguments, sig, this)) return duo;
z_d("51");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "Circle";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(radius)) radius = DS.radius!=null?DS.radius:50;
if (zot(dashed)) dashed = DS.dashed!=null?DS.dashed:false;
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:null;
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:null;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = 1;
if (zot(color)) color = DS.color!=null?DS.color:(borderWidth>0?"rgba(0,0,0,0)":"black");
if (zot(percent)) percent = DS.percent!=null?DS.percent:100;
if (zot(percentClose)) percentClose = DS.percentClose!=null?DS.percentClose:true;
if (zot(strokeObj)) strokeObj = DS.strokeObj!=null?DS.strokeObj:{};
// PICK
var oa = remember(radius, color, borderColor, borderWidth, percent);
function remember() {return arguments;} // for cloning PICK
radius = zim.Pick.choose(radius);
color = zim.Pick.choose(color);
borderColor = zim.Pick.choose(borderColor);
borderWidth = zim.Pick.choose(borderWidth);
percent = zim.Pick.choose(percent);
var that = this;
var _radius = radius;
var _color = color;
var _borderColor = borderColor;
var _borderWidth = borderWidth;
this.mouseChildren = false;
var circle = this.shape = new createjs.Shape();
this.addChild(circle);
var g = circle.graphics;
drawShape();
function drawShape() {
g.c();
that.colorCommand = g.f(_color).command;
if (_color && _color.type) that.specialColor(that.colorCommand, _color);
// border of 0 or a string value still draws a border in CreateJS
if (zot(_borderWidth) || _borderWidth > 0) { // no border specified or a border > 0
if (!zot(_borderColor) || !zot(_borderWidth)) { // either a border color or thickness
if (zot(_borderColor)) _borderColor = "black";
that.borderColorCommand = g.s(_borderColor).command;
if (_borderColor && _borderColor.type) that.specialColor(that.borderColorCommand, _borderColor);
that.borderWidthCommand = g.ss(_borderWidth, strokeObj.caps, strokeObj.joints, strokeObj.miterLimit, strokeObj.ignoreScale).command;
if (dashed) that.borderDashedCommand = g.sd([10, 10], 5).command;
}
}
var h = _radius*2;
if (typeof percent == "number" && percent >= 0 && percent < 100) {
var p = 360*percent/100/2
g.arc(0, 0, _radius, (-p-90)*Math.PI/180, (p-90)*Math.PI/180, false);
if (percentClose) g.cp();
h = _radius-Math.cos(p*Math.PI/180)*_radius;
} else {
g.dc(0,0,_radius);
}
that.setBounds(-_radius,-_radius,_radius*2,h);
}
Object.defineProperty(that, 'color', {
get: function() {
return _color;
},
set: function(value) {
if (zot(value)) value = "black";
_color = value;
if (value && value.type) that.specialColor(that.colorCommand, value);
else {
that.colorCommand.style = value;
}
}
});
var startColor;
var endColor;
this.setColorRange = function(color1, color2) {
if (zot(color2)) {
startColor = that.color;
endColor = color1;
} else if (zot(color1)) {
startColor = that.color;
endColor = color2;
} else {
startColor = color1;
endColor = color2;
}
return that;
}
var _colorRange = 0;
Object.defineProperty(that, 'colorRange', {
get: function() {
return _colorRange;
},
set: function(value) {
_colorRange = value;
if (!zot(startColor) && !zot(endColor)) {
that.color = zim.colorRange(startColor, endColor, value);
}
}
});
Object.defineProperty(that, 'borderColor', {
get: function() {
return _borderColor;
},
set: function(value) {
_borderColor = value;
if (!that.borderColorCommand) drawShape();
else if (value && value.type) that.specialColor(that.borderColorCommand, value);
else that.borderColorCommand.style = value;
}
});
Object.defineProperty(that, 'borderWidth', {
get: function() {
return _borderWidth;
},
set: function(value) {
if (!(value>0)) value = 0;
_borderWidth = value;
if (!that.borderWidthCommand || _borderWidth == 0) drawShape();
else {
that.borderWidthCommand.width = _borderWidth;
if (dashed) {
that.borderDashedCommand.segments = [20, 10];
that.borderDashedCommand.offset = 5;
}
}
}
});
Object.defineProperty(that, 'radius', {
get: function() {
return _radius;
},
set: function(value) {
_radius = value;
drawShape();
}
});
if (style!==false) zimStyleTransforms(this, DS); // global function - would have put on DisplayObject if had access to it
this.linearGradient = function(colors,ratios,x0,y0,x1,y1) {
this.linearGradientParams = Array.prototype.slice.call(arguments);
this.colorCommand.linearGradient(colors,ratios,x0,y0,x1,y1);
return this;
}
this.radialGradient = function(colors,ratios,x0,y0,radius0,x1,y1,radius1) {
this.radialGradientParams = Array.prototype.slice.call(arguments);
this.colorCommand.radialGradient(colors,ratios,x0,y0,radius0,x1,y1,radius1);
return this;
}
this.clone = function(exact) {
var newShape = that.cloneProps(new zim.Circle((exact||!zim.isPick(oa[0]))?that.radius:oa[0], (exact||!zim.isPick(oa[1]))?that.color:oa[1], (exact||!zim.isPick(oa[2]))?that.borderColor:oa[2], (exact||!zim.isPick(oa[3]))?that.borderWidth:oa[3], dashed, (exact||!zim.isPick(oa[4]))?percent:oa[4], percentClose, strokeObj, style, this.group, inherit));
if (that.linearGradientParams) newShape.linearGradient.apply(newShape, that.linearGradientParams);
if (that.radialGradientParams) newShape.radialGradient.apply(newShape, that.radialGradientParams);
return newShape;
}
}
zim.extend(zim.Circle, zim.Container, "clone", "zimContainer", false);
//-51
/*--
zim.Rectangle = function(width, height, color, borderColor, borderWidth, corner, dashed, strokeObj, style, group, inherit)
Rectangle
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Makes a rectangle shape inside a container.
The registration and origin will be top left corner.
NOTE: mouseChildren is turned to false for all zim Shape containers.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var rect = new Rectangle(200, 100, "blue");
rect.center(stage);
// or with rounded corners:
var rect = new Rectangle({width:200, height:100, color:"blue", corner:20});
// or with 2 pixel white stroke
var rect = new Rectangle(200, 100, "blue", "white", 2);
// fill the rectangle with a Bitmap fill assuming icon has been loaded - not the image property
rect.colorCommand.bitmap(frame.asset("icon.png").image);
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports VEE - parameters marked with ZIM VEE mean a zim Pick() object or Pick Literal can be passed
Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - |ZIM VEE| (default the height if provided else 100) the width
height - |ZIM VEE| (default the width if provided else 100) the height
color - |ZIM VEE| (default "black") the fill color as any CSS color including "rgba()" for alpha fill (set a to 0 for tranparent fill)
borderColor - |ZIM VEE| (default null) the stroke color
borderWidth - |ZIM VEE| (default 1 if stroke is set) the size of the stroke in pixels
corner - (default 0) the round of corner
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
dashed - (default false) set to true for dashed border (if borderWidth or borderColor set)
strokeObj - (default {caps:"butt", joints:"miter", miterLimit:10, ignoreScale:false}) set to adjust stroke properties
caps options: "butt", "round", "square" or 0,1,2
joints options: "miter", "round", "bevel" or 0,1,2
miterLimit is the ration at which the mitered joint will be clipped
ignoreScale set to true will draw the specified line thickness regardless of object scale
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
linearGradient([colors],[ratios], x0,y0, x1,y1) - shortcut to colorCommand linearGradient method (see properties below)
radialGradient([colors],[ratios], x0,y0,radius0, x1,y1,radius1) - shortcut to colorCommand radialGradient method (see properties below)
setColorRange(color1, color2) - set a color range for shape - used by colorRange property - returns obj for chaining
if one color is used, the current color is used and color1 is the second color in the range
cache(see Container docs for parameter description) - overrides CreateJS cache() and returns object for chaining
Leave parameters blank to cache bounds of shape (plus outer edge of border if borderWidth > 0)
hasProp(property as String) - returns true if property exists on object else returns false
clone(exact) - makes a copy of the shape
exact (default false) ZIM VEE (Pick) values are active in clones unless exact is set to true
For instance, if the object's color is [blue, green]
then its clone might be blue or green - which could be different than the original
If exact is set to true then the clone will be the color of the original object
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
shape - gives access to the rectangle shape
color - get and set the fill color
colorRange - if setColorRange() is used, the colorRange is a ratio (0-1) between the colors
setting the colorRange will change the color property of the shape
for instance, shape.setColorRange(blue, pink) then shape.colorRange = .5
will set the color of the shape to half way between blue and pink
shape.animate({color:red}, 1000); is a shortcut to animate the colorRange
shape.wiggle("colorRange", .5, .2, .5, 1000, 5000) will wiggle the colorRange
colorCommand - access to the CreateJS fill command for bitmap, linearGradient and radialGradient fills
eg. shape.colorCommand.linearGradient([green, blue ,green], [.2, .5, .8], 0, 0, shape.width, 0)
See: https://www.createjs.com/docs/easeljs/classes/Graphics.Fill.html
borderColor - get and set the stroke color
borderColorCommand - access to the CreateJS stroke command for bitmap, linearGradient and radialGradient strokes
See: https://www.createjs.com/docs/easeljs/classes/Graphics.Stroke.html
borderWidth - get and set the stroke size in pixels
borderWidthCommand - access to the CreateJS stroke style command (width, caps, joints, miter, ignoreScale)
See: https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeStyle.html
borderDashedCommand - access to the CreateJS stroke dashed command (segments, offset)
see https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeDash.html
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
depth - for ZIM VR - the depth used to shift left and right channel and for parallax in VR - also see dep() ZIM Display method
mouseChildren - set to false so you do not drag the shape inside the rectangle
if you nest things inside and want to drag them, will want to set to true
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+52
zim.Rectangle = function(width, height, color, borderColor, borderWidth, corner, dashed, strokeObj, style, group, inherit) {
var sig = "width, height, color, borderColor, borderWidth, corner, dashed, strokeObj, style, group, inherit";
var duo; if (duo = zob(zim.Rectangle, arguments, sig, this)) return duo;
z_d("52");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "Rectangle";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(width)) width = DS.width!=null?DS.width:null;
if (zot(height)) height = DS.height!=null?DS.height:!zot(width)?width:100;
if (zot(width)) width = height;
if (zot(corner)) corner = DS.corner!=null?DS.corner:0;
if (zot(dashed)) dashed = DS.dashed!=null?DS.dashed:false;
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:null;
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:null;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = 1;
if (zot(color)) color = DS.color!=null?DS.color:(borderWidth>0?"rgba(0,0,0,0)":"black");
if (zot(strokeObj)) strokeObj = DS.strokeObj!=null?DS.strokeObj:{};
// PICK
var oa = remember(width, height, color, borderColor, borderWidth);
function remember() {return arguments;} // for cloning PICK
width = zim.Pick.choose(width);
height = zim.Pick.choose(height);
color = zim.Pick.choose(color);
borderColor = zim.Pick.choose(borderColor);
borderWidth = zim.Pick.choose(borderWidth);
var that = this;
var _color = color;
var _borderColor = borderColor;
var _borderWidth = borderWidth;
this.mouseChildren = false;
var rectangle = this.shape = new createjs.Shape();
this.addChild(rectangle);
var g = rectangle.graphics;
drawShape();
function drawShape() {
g.c();
that.colorCommand = g.f(_color).command
if (color && color.type) that.specialColor(that.colorCommand, color);
// border of 0 or a string value still draws a border in CreateJS
if (zot(_borderWidth) || _borderWidth > 0) { // no border specified or a border > 0
if (!zot(_borderColor) || !zot(_borderWidth)) { // either a border color or thickness
if (zot(_borderColor)) _borderColor = "black";
that.borderColorCommand = g.s(_borderColor).command;
if (_borderColor && _borderColor.type) that.specialColor(that.borderColorCommand, _borderColor);
that.borderWidthCommand = g.ss(_borderWidth, strokeObj.caps, strokeObj.joints, strokeObj.miterLimit, strokeObj.ignoreScale).command;
if (dashed) that.borderDashedCommand = g.sd([10, 10], 5).command;
}
}
if (Array.isArray(corner)) {
g.rc(0,0,width,height,corner[0],corner[1],corner[2],corner[3]);
} else if (corner > 0) {
g.rr(0,0,width,height,corner);
} else {
g.r(0,0,width,height);
}
that.setBounds(0,0,width,height);
}
Object.defineProperty(that, 'color', {
get: function() {
return _color;
},
set: function(value) {
if (zot(value)) value = "black";
_color = value;
if (value && value.type) that.specialColor(that.colorCommand, value);
else that.colorCommand.style = value;
}
});
var startColor;
var endColor;
this.setColorRange = function(color1, color2) {
if (zot(color2)) {
startColor = that.color;
endColor = color1;
} else if (zot(color1)) {
startColor = that.color;
endColor = color2;
} else {
startColor = color1;
endColor = color2;
}
return that;
}
var _colorRange = 0;
Object.defineProperty(that, 'colorRange', {
get: function() {
return _colorRange;
},
set: function(value) {
_colorRange = value;
if (!zot(startColor) && !zot(endColor)) {
that.color = zim.colorRange(startColor, endColor, value);
}
}
});
Object.defineProperty(that, 'borderColor', {
get: function() {
return _borderColor;
},
set: function(value) {
_borderColor = value;
if (!that.borderColorCommand) drawShape();
else if (value && value.type) that.specialColor(that.borderColorCommand, value);
else that.borderColorCommand.style = value;
}
});
Object.defineProperty(that, 'borderWidth', {
get: function() {
return _borderWidth;
},
set: function(value) {
if (!(value>0)) value = 0;
_borderWidth = value;
if (!that.borderWidthCommand || _borderWidth == 0) drawShape();
else {
that.borderWidthCommand.width = _borderWidth;
if (dashed) {
that.borderDashedCommand.segments = [20, 10];
that.borderDashedCommand.offset = 5;
}
}
}
});
Object.defineProperty(that, 'corner', {
get: function() {
return corner;
},
set: function(value) {
corner = value;
drawShape();
}
});
if (style!==false) zimStyleTransforms(this, DS);
this.clone = function(exact) {
var newShape = that.cloneProps(new zim.Rectangle((exact||!zim.isPick(oa[0]))?width:oa[0], (exact||!zim.isPick(oa[1]))?height:oa[1], (exact||!zim.isPick(oa[2]))?that.color:oa[2], (exact||!zim.isPick(oa[3]))?that.borderColor:oa[3], (exact||!zim.isPick(oa[4]))?that.borderWidth:oa[4], corner, dashed, strokeObj, style, this.group, inherit));
return newShape;
}
}
zim.extend(zim.Rectangle, zim.Container, "clone", "zimContainer", false);
//-52
/*--
zim.Triangle = function(a, b, c, color, borderColor, borderWidth, center, adjust, dashed, strokeObj, style, group, inherit)
Triangle
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Makes a triangle shape inside a container using three line lengths.
Passing one length parameter makes an equilateral triangle.
Passing two length parameters makes an isosceles triangle.
Passing -1 as the last length parameter makes a 90 degree triangle.
NOTE: mouseChildren is turned to false for all zim Shape containers.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var tri = new Triangle(200, null, null, "green");
tri.center(stage);
// all three sides specified - tall pointy triangle with yellow stroke of 10 pixels
var tri = new Triangle(100, 200, 200, "green", "yellow", 10);
// here we adjust so rotation looks better
var tri = new Triangle({a:200, color:"green", adjust:30});
tri.center(stage);
tri.animate({obj:{rotation:360}, time:3000, ease:"linear", loop:true});
// here we fill the triangle with a linear gradient fill
triangle.colorCommand.linearGradient([green, blue ,green], [.2, .5, .8], 0, 0, triangle.width, 0);
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports VEE - parameters marked with ZIM VEE mean a zim Pick() object or Pick Literal can be passed
Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
a, b and c - |ZIM VEE| (default 100) the lengths of the sides
a will run horizontally along the bottom
b is upwards and c is back to the origin
if c is set to -1 will assume a 90 angle
color - |ZIM VEE| (default "black") the fill color as any CSS color including "rgba()" for alpha fill (set a to 0 for tranparent fill)
borderColor - |ZIM VEE| (default null) the stroke color
borderWidth - |ZIM VEE| (default 1 if stroke is set) the size of the stroke in pixels
center - (default true) puts the registration point to the center
adjust - (default 0) pixels to bring center towards vertical base
the actual center is not really the weighted center
dashed - (default false) set to true for dashed border (if borderWidth or borderColor set)
strokeObj - (default {caps:"butt", joints:"miter", miterLimit:10, ignoreScale:false}) set to adjust stroke properties
caps options: "butt", "round", "square" or 0,1,2
joints options: "miter", "round", "bevel" or 0,1,2
miterLimit is the ration at which the mitered joint will be clipped
ignoreScale set to true will draw the specified line thickness regardless of object scale
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
linearGradient([colors],[ratios], x0,y0, x1,y1) - shortcut to colorCommand linearGradient method (see properties below)
radialGradient([colors],[ratios], x0,y0,radius0, x1,y1,radius1) - shortcut to colorCommand radialGradient method (see properties below)
setColorRange(color1, color2) - set a color range for shape - used by colorRange property - returns obj for chaining
if one color is used, the current color is used and color1 is the second color in the range
cache(see Container docs for parameter description) - overrides CreateJS cache() and returns object for chaining
Leave parameters blank to cache bounds of shape (plus outer edge of border if borderWidth > 0)
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy of the shape
exact (default false) ZIM VEE (Pick) values are active in clones unless exact is set to true
For instance, if the object's color is [blue, green]
then its clone might be blue or green - which could be different than the original
If exact is set to true then the clone will be the color of the original object
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
shape - gives access to the triangle shape
color - get and set the fill color
colorRange - if setColorRange() is used, the colorRange is a ratio (0-1) between the colors
setting the colorRange will change the color property of the shape
for instance, shape.setColorRange(blue, pink) then shape.colorRange = .5
will set the color of the shape to half way between blue and pink
shape.animate({color:red}, 1000); is a shortcut to animate the colorRange
shape.wiggle("colorRange", .5, .2, .5, 1000, 5000) will wiggle the colorRange
colorCommand - access to the CreateJS fill command for bitmap, linearGradient and radialGradient fills
eg. shape.colorCommand.linearGradient([green, blue ,green], [.2, .5, .8], 0, 0, shape.width, 0)
See: https://www.createjs.com/docs/easeljs/classes/Graphics.Fill.html
borderColor - get and set the stroke color
borderColorCommand - access to the CreateJS stroke command for bitmap, linearGradient and radialGradient strokes
See: https://www.createjs.com/docs/easeljs/classes/Graphics.Stroke.html
borderWidth - get and set the stroke size in pixels
borderWidthCommand - access to the CreateJS stroke style command (width, caps, joints, miter, ignoreScale)
See: https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeStyle.html
borderDashedCommand - access to the CreateJS stroke dashed command (segments, offset)
see https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeDash.html
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
depth - for ZIM VR - the depth used to shift left and right channel and for parallax in VR - also see dep() ZIM Display method
one, two, three - read only - points with x, y properties for bottom left, bottom right, top right
angles - read only - Array of angles [bottom left, bottom right, top right]
adjusted - read only - the value of the adjust parameter or 0 if no adjust was supplied
mouseChildren - set to false so you do not drag the shape inside the triangle
if you nest things inside and want to drag them, will want to set to true
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+53
zim.Triangle = function(a, b, c, color, borderColor, borderWidth, center, adjust, dashed, strokeObj, style, group, inherit) {
var sig = "a, b, c, color, borderColor, borderWidth, center, adjust, dashed, strokeObj, style, group, inherit";
var duo; if (duo = zob(zim.Triangle, arguments, sig, this)) return duo;
z_d("53");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "Triangle";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(a)) a = DS.a!=null?DS.a:100;
if (zot(b)) b = DS.b!=null?DS.b:a;
if (zot(c)) c = DS.c!=null?DS.c:b;
if (c==-1) c = Math.sqrt(Math.pow(a,2)+Math.pow(b,2));
if (zot(center)) center = DS.center!=null?DS.center:true;
if (zot(adjust)) adjust = DS.adjust!=null?DS.adjust:0;
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:null;
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:null;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = 1;
if (zot(color)) color = DS.color!=null?DS.color:(borderWidth>0?"rgba(0,0,0,0)":"black");
if (zot(adjust)) adjust = DS.adjust!=null?DS.adjust:0;
if (zot(strokeObj)) strokeObj = DS.strokeObj!=null?DS.strokeObj:{};
// PICK
var oa = remember(a, b, c, color, borderColor, borderWidth);
function remember() {return arguments;} // for cloning PICK
a = zim.Pick.choose(a);
b = zim.Pick.choose(b);
c = zim.Pick.choose(c);
this.a = a;
this.b = b;
this.c = c;
color = zim.Pick.choose(color);
borderColor = zim.Pick.choose(borderColor);
borderWidth = zim.Pick.choose(borderWidth);
var that = this;
var _color = color;
var _borderColor = borderColor;
var _borderWidth = borderWidth;
this.mouseChildren = false;
var lines = [a,b,c];
lines.sort(function(a, b){return b-a});
var aa = lines[0];
var bb = lines[1];
var cc = lines[2];
var order = [lines.indexOf(a), lines.indexOf(b), lines.indexOf(c)];
if (aa > bb+cc) {
zog("zim display - Triangle(): invalid triangle lengths");
return;
}
var tri = this.shape = new createjs.Shape();
this.adjusted = adjust;
this.addChild(tri);
var g = tri.graphics;
drawShape();
function drawShape() {
g.c();
that.colorCommand = g.f(_color).command;
if (_color && _color.type) that.specialColor(that.colorCommand, _color);
// border of 0 or a string value still draws a border in CreateJS
if (zot(_borderWidth) || _borderWidth > 0) { // no border specified or a border > 0
if (!zot(_borderColor) || !zot(_borderWidth)) { // either a border color or thickness
if (zot(_borderColor)) _borderColor = "black";
that.borderColorCommand = g.s(_borderColor).command;
if (_borderColor && _borderColor.type) that.specialColor(that.borderColorCommand, _borderColor);
that.borderWidthCommand = g.ss(_borderWidth, strokeObj.caps, strokeObj.joints, strokeObj.miterLimit, strokeObj.ignoreScale).command;
if (dashed) that.borderDashedCommand = g.sd([10, 10], 5).command;
}
}
g.mt(0,0);
that.one={x:0,y:0};
g.lt(a,0);
that.two={x:a,y:0};
// find biggest angle with cosine rule
var angle1 = Math.acos( (Math.pow(bb,2) + Math.pow(cc,2) - Math.pow(aa,2)) / (2 * bb * cc) ) * 180 / Math.PI;
// use the sine rule for next biggest angle
var angle2 = Math.asin( bb * Math.sin(angle1 * Math.PI / 180) / aa ) * 180 / Math.PI;
// find last angle
var angle3 = 180 - angle1 - angle2;
// get position of angles by mapping to opposite side sizes
// as in smallest angle is across from smallest side
// largest angle is across from largest size, etc.
var temp = [angle1, angle2, angle3]; // largets to smallest
that.angles = [temp[order[1]], temp[order[2]], temp[order[0]]];
var nextAngle = that.angles[1];
var backX = Math.cos(nextAngle * Math.PI / 180) * b;
var upY = Math.sin(nextAngle * Math.PI / 180) * b;
var width = Math.max(a, a-backX);
var height = upY
that.setBounds(0,adjust,width,height);
tri.y = height;
g.lt(a-backX,0-upY);
that.three={x:a-backX,y:0-upY};
g.cp();
if (center) {
that.regX = width/2;
that.regY = height/2;
}
if (adjust) {
that.shape.y+=adjust;
}
}
Object.defineProperty(that, 'color', {
get: function() {
return _color;
},
set: function(value) {
if (zot(value)) value = "black";
_color = value;
if (value && value.type) that.specialColor(that.colorCommand, value);
else that.colorCommand.style = value;
}
});
var startColor;
var endColor;
this.setColorRange = function(color1, color2) {
if (zot(color2)) {
startColor = that.color;
endColor = color1;
} else if (zot(color1)) {
startColor = that.color;
endColor = color2;
} else {
startColor = color1;
endColor = color2;
}
return that;
}
var _colorRange = 0;
Object.defineProperty(that, 'colorRange', {
get: function() {
return _colorRange;
},
set: function(value) {
_colorRange = value;
if (!zot(startColor) && !zot(endColor)) {
that.color = zim.colorRange(startColor, endColor, value);
}
}
});
Object.defineProperty(that, 'borderColor', {
get: function() {
return _borderColor;
},
set: function(value) {
_borderColor = value;
if (!that.borderColorCommand) drawShape();
else if (value && value.type) that.specialColor(that.borderColorCommand, value);
else that.borderColorCommand.style = value;
}
});
Object.defineProperty(that, 'borderWidth', {
get: function() {
return _borderWidth;
},
set: function(value) {
if (!(value>0)) value = 0;
_borderWidth = value;
if (!that.borderWidthCommand || _borderWidth == 0) drawShape();
else {
that.borderWidthCommand.width = _borderWidth;
if (dashed) {
that.borderDashedCommand.segments = [20, 10];
that.borderDashedCommand.offset = 5;
}
}
}
});
this.linearGradient = function(colors,ratios,x0,y0,x1,y1) {
this.linearGradientParams = Array.prototype.slice.call(arguments);
this.colorCommand.linearGradient(colors,ratios,x0,y0,x1,y1);
return this;
}
this.radialGradient = function(colors,ratios,x0,y0,radius0,x1,y1,radius1) {
this.radialGradientParams = Array.prototype.slice.call(arguments);
this.colorCommand.radialGradient(colors,ratios,x0,y0,radius0,x1,y1,radius1);
return this;
}
if (style!==false) zimStyleTransforms(this, DS);
this.clone = function(exact) {
var newShape = that.cloneProps(new zim.Triangle((exact||!zim.isPick(oa[0]))?a:oa[0], (exact||!zim.isPick(oa[1]))?b:oa[1], (exact||!zim.isPick(oa[2]))?c:oa[2], (exact||!zim.isPick(oa[3]))?that.color:oa[3], (exact||!zim.isPick(oa[4]))?that.borderColor:oa[4], (exact||!zim.isPick(oa[5]))?that.borderWidth:oa[5], center, adjust, dashed, strokeObj, style, this.group, inherit));
if (that.linearGradientParams) newShape.linearGradient.apply(newShape, that.linearGradientParams);
if (that.radialGradientParams) newShape.radialGradient.apply(newShape, that.radialGradientParams);
return newShape;
}
}
zim.extend(zim.Triangle, zim.Container, "clone", "zimContainer");
//-53
/*--
zim.Squiggle = function(color, thickness, points, length, controlLength, controlType, lockControlType, showControls, lockControls, handleSize, allowToggle, move, dashed, onTop, stickColor, selectColor, selectPoints, editPoints, interactive, strokeObj, style, group, inherit)
Squiggle
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Makes a squiggly line with a number of points.
The points have Bezier controls - little handles that change the shape of the line.
The type of control can be specified overall and individually - and can be hidden or shown
The type of control can be changed by double clicking the point - colors of the handles will change
Points can be added by clicking on the line or removed by SHIFT clicking a point.
CTRL Z will undo adding or removing a point
The shape of the line can be recorded with the recordData() method and recreated with the setData() method
The Squiggle is set by default to show and hide controls when clicked
It is also draggable by default when the controls are showing
It can be set to copy with a shift click
MULTIPLE SELECT
Multiple points can be selected and dragged or moved with the keyboard arrows (moves 10 pixels with shift key down)
NOTE: mouseChildren is turned to false for all zim Shape containers.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var squiggle = new Squiggle().center(); // makes a line with default 4 points with Bezier controls
var line = new Squiggle({points:2, controlType:"none"}).pos(100,100); // makes a diagonal straight line that is editable
END EXAMPLE
EXAMPLE
// Animate along a Squiggle
// see https://zimjs.com/explore/squiggleAnimate.html for more
var line = new Squiggle().center();
new Circle(10, red).addTo().animate({path:line}, 1000);
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports VEE - parameters marked with ZIM VEE mean a zim Pick() object or Pick Literal can be passed
Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
color - |ZIM VEE| - (default green) the line color as any CSS color including "rgba()" for alpha
thickness - (default 2) the thickness of the line in pixels
points - (default 4)a number of points to start with to make the shape
OR an SVG path like: points:"M0,129.5c22,0,40-31,40-41c0-8-3.2-13-10-13" etc. (also see SVGContainer)
OR an array of points as follows:
[[controlX, controlY, circleX, circleY, rect1X, rect1Y, rect2X, rect2Y, controlType], [etc]]
controlX and controlY - the x and y location of the control Container which holds the point circle and the two control rectangles
rect1X, rect1Y, rect2X, rect2Y - (default based on controlLength) the x and y location of the control rectangles relative to the control location
circleX and circleY - (default 0) the x and y location of the circle relative to the control location (usually 0, 0)
controlType - (default main controlType parameter or "straight" if not controlType parameter) the point's controlType "none", "mirror", "straight" or "free"
length - (default 300) the default length of line used to create the squiggle (also specifies the squiggle's bounds(0, 0, length, thickness))
controlLength - |ZIM VEE| (default radius*numPoints/4) specify a Number to override the calculated default
controlType - (default "straight") one of four String values as follows:
none - there are no control rectangles (they are actually set at 0,0). This makes a corner at the circle point.
mirror - the control rectangles reflect one another about the point circle - lengths are kept even
straight - the control rectangles keep a straight line through the point circle but length is independent
free - the control rectangle moves independently from the other control rectangle
** The controlType can be specified for each point - see the points parameter
** The controlType can be changed by doubleClicking the point circle to cycle through the controls in the order above - unless the lockControlType is set to true
lockControlType - (default false) set to true to disable doubleClicking of point circles to change controlType
showControls - (default true) set to false to start with controls not showing - can change this after with controlsVisible property or showControls() and hideControls() methods
lockControls - (default false) set to true to lock the editing of controls - can't move the points or handles - but can see them if showControls is set to true
handleSize - (default 20 mobile 10 for non-mobile) the size of control boxes and affects the circles too proportionally
allowToggle - (default true) set false to let turn off clicks showing and hiding controls
move - (default true) set to false to disable dragging when controls are showing
can also set to "always" to allow movement when controls are not showing
dashed - (default false) set to true for dashed border (if borderWidth or borderColor set)
onTop - (default true) set to false to not bring shape to top of container when dragging
stickColor - (default "#111") set the stick color of the controls
selectColor - (default white) the color of the selected circle or rectangle of the controls if selectPoints is true
selectPoints - (default true) set to false to not allow point controls to be selected for keyboard control
editPoints - (default true) lets user add points by pressing on shape path or remove points by shift click or hold
set to "anywhere" to let users add points anywhere - will add points with controlType:"none"
set to false to not allow adding or removing points with shift click or hold
interactive - (default true) set to false to turn off controls, move, toggle, select, edit - leaving just the shape
strokeObj - (default {caps:"butt", joints:"miter", miterLimit:10, ignoreScale:false}) set to adjust stroke properties
caps options: "butt", "round", "square" or 0,1,2
joints options: "miter", "round", "bevel" or 0,1,2
miterLimit is the ration at which the mitered joint will be clipped
ignoreScale set to true will draw the specified line thickness regardless of object scale
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
approximateBounds(num, showPoints) - update the bounds based on a Rectangle
that surrounds the number of points (default 80) distributed around the object path
set showPoints to true to draw little dots on points
use outline() after object has been added to the stage to see the bounds
addPoint(percent, controlType) - add a point at a percent (100) of the total curve
this is handy to make path have the same number of points for animate() path tweens
controlType can be as specified in main points parameter
returns object for chaining
addPoints(num, controlType, startPoint, spread, dataOnly, points) - add num points between existing points
controlType can be as specified in main points parameter
specify a startPoint to add points between the startPoint and the next point (one segment of points)
spread (default false) set to true to spread points evenly around path rather than evenly between segments
dataOnly and points are used internally
returns object for chaining
interpolate(num, startPoint, spread, points, even) - get point data {x,y} for existing points and num (default 1) points inbetween
used with hitTestPath() and animate() drag on path - also add points (note add points does not use even:true)
specify a startPoint to get points between the startPoint and the next point (one segment of points)
spread (default false) set to true to spread number of points around path rather equal number between segments
points (default all points) the points to work with in the same format as the points property
even (default false) set to true to use zim.Bezier() with even turned on for even percentage distribution
returns an array of point objects with x, y properties and an r property for ratio of distance along path
recordData(toJSON) - returns an object with x, y, points, color, borderColor, borderWidth, move, toggle, controls PROPERTIES to be used with setData() method
if toJSON (default false) is set to true, the return value is a JSON string
the points data comes from the points property
setData(data, fromJSON) - sets the properties to match the data object passed in - this should come from recordData()
if fromJSON (default false) is set to true, it will assume a JSON string is passed in as data
the points data is parsed with the set setPoints() so the number of points should be the same
returns object for chaining
recordPoints(popup) - returns an array with the same format as the points parameter - or can just use points property
popup - (default false) set to true to open a zim Pane (squiggle.pane) with the points in a zim TextArea (squiggle.textArea) (click off to close)
NOTE: the TextArea output uses JSON.stringify() - to add the points to the points parameter of the Squiggle use JSON.parse(output);
NOTE: using zog(JSON.stringify(squiggle.recordData()))... the console will remove the quotes from the controlTypes so those would have to be manually put back in before parse() will work
setPoints(data) - sets the Squiggle points to the data from recordPoints
This does not remake the Squiggle but rather shifts the controls so the number of points should be the same
changeControl(index, type, rect1X, rect1Y, rect2X, rect2Y, circleX, circleY, update) - change a control type and properties at an index
accepts ZIM DUO normal parameters or configuration object literal with parameter names as propterties
passing in null as the index will change all points to the specified properties
the update parameter defaults to false so set to true to show update or call update() below
this is so multiple changes can be batched before calling update - for instance when animating blobs.
transformPoints(transformType, amount, x, y) - scale, rotate, move points without affecting controls or borderWidth - returns object for chaining
Note - does not adjust original Bounds
transformType - String any of: "scale", "scaleX", "scaleY", "rotation", "x", "y"
amount - the amount to transform
x, y - (default 0, 0) the x and y position to transform about
update(normalize) - update the Squiggle if animating control points, etc. would do this in a Ticker
set normalize (default false) to true to use pointsAdjusted for rotated and scaled points
and if animating along the path after setting rotation or scale on point
just leave out if only animating points
showControls() - shows the controls (and returns squiggle) also see controlsVisible property
hideControls() - hides the controls (and returns squiggle) also see controlsVisible property
toggle(state - default null) - shows controls if hidden and hides controls if showing (returns the object for chaining)
or pass in true to show controls or false to hide controls
traverse(obj, start, end, time) - animates obj from start point to end point along path - thanks KV for the thought!
set start point greater than end point to traverse backwards
will dispatch a "traversed" event when done
setColorRange(color1, color2) - set a color range for shape - used by colorRange property - returns obj for chaining
if one color is used, the current color is used and color1 is the second color in the range
getPointAngle(index) - gets the angle made by the tangent at the index provided
getSegmentPoint(point1, point2) - returns an array of [point1, controlPoint1, controlPoint2, point2]
used internally for animating to path and adding removing Bezier points
getAdjacentSegmentData(index) - returns an array of two arrays:
The first is an array of cubic Bezier points for segments adjacent and including the provided point index
each element is in the form of [point1, controlPoint1, controlPoint2, point2]
The second is an array of starting point indexes for the segments that were tested
used internally to drag an animation along the path
getCurvePoint(ratio, segmentRatios, segmentPoints, getAngle) gets a point along whole curve at the ratio (0-1) provided
along with x and y values, the point has a z value that is the index of the squiggle point before the calculated point
if the getAngle parameter is true (default false) the point also has an angle property which is the angle of the tangent at the point
ratio is 0-1 with 0 being at the first point and 1 being at the end of the last segment
segmentRatios and segmentPoints will be calculated if not provided
used internally for animating along the path - if lockControls is true, only animate will precalculate these values
linearGradient([colors],[ratios], x0,y0, x1,y1) - shortcut to thicknessCommand linearGradient method (see properties below)
radialGradient([colors],[ratios], x0,y0,radius0, x1,y1,radius1) - shortcut to thicknessCommand radialGradient method (see properties below)
cache(see Container docs for parameter description) - overrides CreateJS cache() and returns object for chaining
Leave parameters blank to cache bounds of shape (plus outer edge of border if borderWidth > 0)
hasProp(property as String) - returns true if property exists on object else returns false
clone(exact, commands) - makes a copy of the object
exact (default false)
ZIM VEE (Pick) values are active in clones unless exact is set to true
For instance, if the object's color is [blue, green]
then its clone might be blue or green - which could be different than the original
If exact is set to true then the clone will be the color of the original object
commands (default false) makes clones with current color and borderColor commands of object
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
shape - gives access to the shape of the squiggle
color - get and set the fill color
colorRange - if setColorRange() is used, the colorRange is a ratio (0-1) between the colors
setting the colorRange will change the color property of the shape
for instance, shape.setColorRange(blue, pink) then shape.colorRange = .5
will set the color of the shape to half way between blue and pink
shape.animate({color:red}, 1000); is a shortcut to animate the colorRange
shape.wiggle("colorRange", .5, .2, .5, 1000, 5000) will wiggle the colorRange
stickColor - get or set the stickColor - requires an update() to see changes
colorCommand - access to the CreateJS fill command for bitmap, linearGradient and radialGradient fills
eg. shape.colorCommand.linearGradient([green, blue ,green], [.2, .5, .8], 0, 0, shape.width, 0)
See: https://www.createjs.com/docs/easeljs/classes/Graphics.Fill.html
thickness - get and set the stroke size in pixels
thicknessCommand - access to the CreateJS stroke style command (width, caps, joints, miter, ignoreScale)
See: https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeStyle.html
dashedCommand - access to the CreateJS stroke dashed command (segments, offset)
see https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeDash.html
num - get the number of points - to set, use the points property
points - get or set the points array of the Squiggle in the same format as the points parameter:
[[controlX, controlY, circleX, circleY, rect1X, rect1Y, rect2X, rect2Y, controlType], [etc]]
pointsAdjusted - get points with any point rotation converted to 0 - see update(true)
pointControls - get an array of controls (a container) - use this to animate controls
pointCircles - get an array of control circles - use this to place some other object at the point
pointObjects - get an array of point objects for each point in the following format:
[[control, circle, rect1, rect2, controlType], [etc.]]
control - the container for the control that holds the circle and rectangles (also see pointControls)
circle - the control point circle (also see pointCircles)
rect1 - the first control point rectangle
rect2 - the second control point rectangle
controlType - the control type: default is "straight" (or null) and there is also "mirror", "free" and "none"
NOTE: control, circle, rect1, rect2 can be positioned or animated and controlType can be changed
NOTE: the update() method must be called if manually changing the control positions or type
NOTE: if constantly animating the controls then use a Ticker.add(function(){squiggle.update();})
NOTE: also see recordData(), setData(), recordPoints(), setPoints() methods for further options
addPointFactor - (default 20) used when placing new points along edge (editPoints is true)
divides the distance between points by this amount - the smaller the more accurate but also slower
addMinDistance - (default 15) edge press needs to be within this distance to add a point to the edge
segmentPoints - a read-only array of cubic Bezier points for each segment
each element is in the form of [point1, controlPoint1, controlPoint2, point2]
used internally to animate to the path and add and remove Bezier points
segmentRatios - a read-only array of cumulative ratio lengths of segments
for instance the default five points (four segments) is [.25, .5, .75, 1]
used internally to animate to the path and attribute proportional time to each segment
controls - access to the container that holds the sets of controls
each control is given a read-only num property
sticks - access to the container that holds the control sticks
lastSelected - access to the last selected (or created) control container
lastSelectedIndex - the index number of the last selected controls
controlsVisible - get or set the visibility of the controls - or use showControls() and hideControls()
toggled - read-only Boolean property as to whether picker is showing
types - get or set the general array for the types ["mirror", "straight", "free", "none"]
changing this or removing a type will adjust the order when the user double clicks the points to change their type
this is not an array of types for each point - see the points property to access the types of each point
lockControls - Boolean to lock controls from being adjusted or not
lockControlType - Boolean to lock the type of the controls in their current state or not
allowToggle - Boolean to get or set clicking to show and hide controls
move - Boolean to drag or not drag Squiggle when controls are showing
can also set to "always" to allow movement when controls are not showing
onTop - get or set the onTop
selectPoints - get or set whether points can be selected
interactive - get or set whether the shape is interactive - toggle, move, change or add controls, etc.
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
depth - for ZIM VR - the depth used to shift left and right channel and for parallax in VR - also see dep() ZIM Display method
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
keyFocus - get or set the keyboard focus on the DisplayObject - see also zim.KEYFOCUS
will be set to true if this DisplayObject is the first made or DisplayObject is the last to be used with keyboard
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
dispatches a "change" event for when the bezier controls are adjusted (pressup only)
if monitoring constant change is needed add a pressmove event to Squiggle.controls
the change event object has a transformType property with values of "move", "bezierPoint", "bezierHandle", "bezierSwitch"
dispatches "controlsshow" and "controlshide" events when clicked off and on and toggle is true
dispatches an "update" event if the points are changed or a point is added or removed
this removes all listeners on the old shape and controls
so any custom listeners on shape and controls will need to be re-applied - use the update event to do so
dispatches a "traversed" event when traverse() is done - the event object has an obj property for the traversing object
See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
MORE
https://zimjs.com/squiggle
https://www.youtube.com/watch?v=BA1bGBU4itI&list=PLCIzupgRt1pYtMlYPtNTKCtztFBeOtyc0
Note the points property has been split into points and pointObjects (and there have been a few property changes) since the time of the video
--*///+53.2
zim.Squiggle = function(color, thickness, points, length, controlLength, controlType, lockControlType, showControls, lockControls, handleSize, allowToggle, move, dashed, onTop, stickColor, selectColor, selectPoints, editPoints, interactive, strokeObj, style, group, inherit) {
var sig = "color, thickness, points, length, controlLength, controlType, lockControlType, showControls, lockControls, handleSize, allowToggle, move, dashed, onTop, stickColor, selectColor, selectPoints, editPoints, interactive, strokeObj, style, group, inherit";
var duo; if (duo = zob(zim.Squiggle, arguments, sig, this)) return duo;
z_d("53.2");
this.group = group;
var DS = style===false?{}:zim.getStyle("Squiggle", this.group, inherit);
if (zot(thickness)) thickness = DS.thickness!=null?DS.thickness:6;
if (zot(length)) length = DS.length!=null?DS.length:300;
if (zot(points)) points = DS.points!=null?DS.points:5;
if (typeof points == "string") {
var svgProcessor = new zim.SVGContainer();
points = svgProcessor.processPath(points);
}
var num = typeof points == "number" ? points : points.length;
if (num == 0) return;
if (zot(controlLength)) controlLength = DS.controlLength!=null?DS.controlLength:(length / num);
this.zimContainer_constructor(length, controlLength, null, null, false);
this.type = "Squiggle";
if (zot(dashed)) dashed = DS.dashed!=null?DS.dashed:false;
if (zot(color)) color = DS.color!=null?DS.color:zim.blue;
if (color.style) {this.colorCommand = color; color = "black";}
if (zot(controlType)) controlType = DS.controlType!=null?DS.controlType:null;
var originalControlType = controlType;
if (zot(controlType)) controlType = "mirror";
if (zot(lockControlType)) lockControlType = DS.lockControlType!=null?DS.lockControlType:false;
if (zot(interactive)) interactive = DS.interactive!=null?DS.interactive:true;
if (zot(showControls)) showControls = DS.showControls!=null?DS.showControls:interactive;
var _controls = showControls;
if (zot(lockControls)) lockControls = DS.lockControls!=null?DS.lockControls:!interactive;
if (zot(handleSize)) handleSize = DS.handleSize!=null?DS.handleSize:zim.mobile()?20:10;
if (zot(allowToggle)) allowToggle = DS.allowToggle!=null?DS.allowToggle:interactive;
if (zot(move)) move = DS.move!=null?DS.move:interactive;
if (zot(stickColor)) stickColor = DS.stickColor!=null?DS.stickColor:"#111";
if (zot(selectColor)) selectColor = DS.selectColor!=null?DS.selectColor:"#fff";
if (zot(selectPoints)) selectPoints = DS.selectPoints!=null?DS.selectPoints:interactive;
this.stickColor = stickColor;
if (zot(onTop)) onTop = DS.onTop!=null?DS.onTop:true;
if (zot(editPoints)) editPoints = DS.editPoints!=null?DS.editPoints:interactive;
if (zot(strokeObj)) strokeObj = DS.strokeObj!=null?DS.strokeObj:{};
var oa = remember(color);
function remember() {return arguments;} // for cloning PICK
color = zim.Pick.choose(color);
var that = this;
var types = this.types = ["mirror", "straight", "free", "none"];
this.interactive = interactive;
this.num = num;
this.onTop = onTop;
this.move = move;
this.editPoints = editPoints;
this.allowToggle = allowToggle;
this.lockControlType = lockControlType;
this.selectPoints = selectPoints;
this.lockControls = lockControls;
var _points;
var _pointCircles;
var _pointControls;
var _color = color;
var _thickness = thickness;
var shape;
var moveDownEvent;
var movePressEvent;
var moveUpEvent;
var stage;
var draggingCheck = that.move;
var min = 2; // min distance within which a click will add a point
var mapMove;
var drawShape;
var sets;
if (originalControlType && typeof points != "number") {
// override controlType
loop(points, function(point) {
point[8]=originalControlType;
if (originalControlType == "none") {
point[4]=point[5]=point[6]=point[7]=0;
}
});
}
init();
function init() {
if (sets) sets.removeAllEventListeners();
that.num = num = typeof points == "number" ? points : points.length;
num = Math.max(2,num);
controlLength = length / num;
shape = that.shape = new zim.Shape({style:false}).addTo(that);
var sticks = that.sticks = new zim.Shape({style:false}).addTo(that);
if (handleSize <= 0) sticks.removeFrom();
var g = shape.graphics;
g.c();
var s = sticks.graphics;
s.c();
var ballS = handleSize/10*8;
var rectS = handleSize;
if (that.selectPoints) {
that.selectedBalls = new zim.SelectionSet();
that.selectedRect1s = new zim.SelectionSet();
that.selectedRect2s = new zim.SelectionSet();
that.selectionManager = new zim.SelectionManager([
that.selectedBalls,
that.selectedRect1s,
that.selectedRect2s
], "ctrl", false);
} else {
that.selectionManager = new zim.SelectionManager(null, "ctrl");
}
var mobile = zim.mobile();
sets = that.controls = new zim.Container({style:false}).addTo(that); // sets - a set contains a ball and two rects
if (that.interactive) sets.drag({onTop:!mobile});
_points = [];
_pointControls = [];
_pointCircles = [];
var angle, point, temp, set, rect1, rect2, ball, type, setInfo;
for (var i=0; i 0) {
for(var i=0; i 0) {
diffX = e.target.x-e.target.startX;
diffY = e.target.y-e.target.startY;
for(var i=0; i0) {
for(var i=0; i endPercent || obj.percentComplete == 0) {
obj.stopAnimate();
e.remove();
var eventObj = new createjs.Event("traversed");
eventObj.obj = obj;
that.dispatchEvent(eventObj);
}
});
return that;
}
that.update = function(normalize) {
if (normalize) {
// located any rotated or scaled points
// and set them back to non-rotated and non-scaled
// but keep control handles at the earlier positions
// need to normalize before doing more manual updates with Beziers
// do not need to normalize if animating blob points
that.points = that.pointsAdjusted;
} else {
drawShape();
}
that.zimAnimateChanged = true;
return that;
}
// squiggle
if (that.interactive) {
if (move) shape.drag({onTop:false});
moveDownEvent = shape.on("mousedown", function(e) {
stage = e.target.stage;
startPosition = {x:shape.x, y:shape.y};
if (that.selectPoints) that.keyFocus = true;
upTop();
});
movePressEvent = shape.on("pressmove", function() {
sets.x = shape.x;
sets.y = shape.y;
sticks.x = shape.x;
sticks.y = shape.y;
});
moveUpEvent = shape.on("pressup", function() {
var moveControlCheck = (shape.x != startPosition.x || shape.y != startPosition.y);
var movePoint = shape.localToLocal(that.regX,that.regY,that.parent);
that.x = movePoint.x;
that.y = movePoint.y;
sets.x = sets.y = sticks.x = sticks.y = shape.x = shape.y = 0;
if (moveControlCheck) {
var ev = new createjs.Event("change");
ev.controlType = "move";
that.dispatchEvent(ev);
}
stage.update();
});
if (!that.move) stopDragging(true); // true is first time
}
function upTop() {
if (that.onTop) {
var nc = that.parent.numChildren-1;
if (that.parent.getChildAt(nc).type == "Keyboard") nc--;
that.parent.setChildIndex(that, nc);
}
}
that.toggleEvent = that.on("mousedown", function() {
if (!that.allowToggle) return;
if (!_controls) {
that.showControls();
that.dispatchEvent("controlsshow");
}
});
that.added(function() {
that.toggleStageEvent = that.stage.on("stagemousedown", function(e) {
if (!that.allowToggle || !that.stage) return;
if (_controls && !that.hitTestPoint(e.stageX/zim.scaX, e.stageY/zim.scaY, false)) {
that.hideControls();
that.dispatchEvent("controlshide");
}
});
});
that.clickEvent = that.on("click", function() {
if (that.ctrlKey) {
setTimeout(function() { // give time for record to work if drag with ctrl down
that.clone(true).addTo(that.stage).mov(0, 100);
if (that.allowToggle) {
that.hideControls();
that.dispatchEvent("controlshide");
}
var ev = new createjs.Event("change");
ev.controlType = "move";
that.dispatchEvent(ev);
that.stage.update();
}, 50);
}
});
that.hideControls = function() {
that.toggled = false;
sets.visible = false;
sticks.visible = false;
_controls = false;
if (that.stage) that.stage.update();
if (!that.allowToggle && that.move) stopDragging();
return that;
}
if (!showControls) that.hideControls();
that.showControls = function() {
that.toggled = true;
// if call this with code then will not trigger a change event - not good for TransformManager.persist()
sets.visible = true;
sticks.visible = true;
_controls = true;
sets.x = shape.x;
sets.y = shape.y;
sticks.x = shape.x;
sticks.y = shape.y;
that.addChildAt(shape,0); // put to bottom incase dragged
if (that.move && !that.allowToggle) startDragging();
if (that.stage) that.stage.update();
return that;
}
that.toggle = function(state) {
if (state===true) that.showControls();
else if (state===false) that.hideControls();
else if (_controls) that.hideControls();
else that.showControls();
return that;
}
that.recordData = function(toJSON) {
if (zot(toJSON)) toJSON = false;
var obj = {
type:"Blob",
index:that.parent?that.parent.getChildIndex(that):-1,
x:that.x, y:that.y,
points:that.recordPoints(),
color:that.color,
thickness:that.thickness,
move:that.move,
toggle:that.allowToggle,
controlsVisible:_controls
}
if (toJSON) return JSON.stringify(obj);
return obj;
}
that.setData = function(data, fromJSON) {
if (zot(data)) return;
if (fromJSON) {
try{
data = JSON.parse(data);
} catch(e) {
return;
}
}
var index = data.index;
if (zot(index)) index = -1;
delete data.index;
var pointData = data.points;
if (!zot(pointData)) that.setPoints(pointData);
delete data.points;
that.num = pointData.length;
for (var d in data) {
that[d] = data[d];
}
if (that.parent) {
that.parent.setChildIndex(that, index);
}
that.update();
return that;
}
that.recordPoints = function(popup) {
// balls are relative to blob but handles are relative to ball
// points is an array of [[ballX, ballY, handleX, handleY, handle2X, handle2Y, type], etc.]
if (zot(popup)) popup = false;
var points = that.points;
if (popup) {
if (!that.pane) {
var pane = that.pane = new zim.Pane({
container:that.stage,
width:Math.min(500, that.stage.width-20),
height:Math.min(500, that.stage.height-20),
draggable:true,
});
var textArea = that.textArea = new zim.TextArea(Math.min(400, that.stage.width-70), Math.min(400, that.stage.height-70));
textArea.centerReg(pane);
}
that.textArea.text = JSON.stringify(points);
that.pane.show();
}
return points;
}
that.setPoints = function(points) {
// adjust blob to match points passed in from recordPoints
var p;
var p2;
for (var i=0; i0?ratios[pointBefore-1]:0;
that.addPoint(100*(lastRatio+(currentRatio-lastRatio)*((closestIndex)/(testNum+1))));
}
}
that.lastSelectedIndex = pointBefore+1;
that.lastSelected = that.controls.getChildAt(that.lastSelectedIndex);
that.stage.update();
}
});
// remove point
that.controls.on("click", function (e) {
that.lastSelected = e.target.parent;
var index = that.lastSelectedIndex = that.controls.getChildIndex(e.target.parent);
if (!that.editPoints) return;
if (that.selectionManager.shiftKey) { // remove
// if (that.selectionManager.currentSet == that.selectedBalls && that.selectedBalls.selections.length > 0) return;
removeControl(e);
}
});
function removeControl(e) {
if (e.target.type == "Circle") {
var index = that.lastSelectedIndex = that.controls.getChildIndex(e.target.parent);
if (that.controls.numChildren <= 2) return;
var points = that.points;
if (that.selectPoints) that.lastPoints = zim.copy(points);
points.splice(index, 1); // remove the point at the index
that.points = points;
that.stage.update();
that.lastSelected = that.lastSelectedIndex = null;
}
}
that.controls.hold(removeControl);
if (!_controls) that.hideControls();
that.dispatchEvent("update");
} // end of init()
// if (that.selectPoints) {
function getCurrentSelected() {
var answer = [];
var currentSet = that.selectionManager.currentSet;
if (currentSet && currentSet.selections && currentSet.selections.length > 0) {
for(var i=0; i= 37 && e.keyCode <= 40) {
var currentSelected = getCurrentSelected();
if (currentSelected.length > 0) {
for(var i=0; i= 37 && e.keyCode <= 40) {
var currentSelected = getCurrentSelected();
if (currentSelected.length > 0) {
for(var i=0; i0)) value = 0;
_thickness = value;
if (!that.thicknessCommand || _thickness == 0) drawShape();
else {
that.thicknessCommand.width = _thickness;
if (dashed) {
that.borderDashedCommand.segments = [20, 10];
that.borderDashedCommand.offset = 5;
}
}
}
});
if (typeof KEYFOCUS !== typeof undefined) zim.KEYFOCUS = KEYFOCUS;
Object.defineProperty(this, 'keyFocus', {
get: function() {
return zim.KEYFOCUS == that;
},
set: function(value) {
zim.KEYFOCUS = that;
}
});
if (!zim.KEYFOCUS) setFocus();
function setFocus() {if (!that.selectPoints) return; that.keyFocus = true; var d=document.activeElement; if (d) d.blur();}
Object.defineProperty(that, 'points', {
get: function() {
var points = [];
var point; var p;
for (var i=0; i<_points.length; i++) {
p = _points[i];
point = [
zim.decimals(p[0].x),
zim.decimals(p[0].y),
zim.decimals(p[1].x),
zim.decimals(p[1].y),
zim.decimals(p[2].x),
zim.decimals(p[2].y),
zim.decimals(p[3].x),
zim.decimals(p[3].y)
];
if (p[4] && p[4]!=="mirror") point.push(p[4])
points.push(point);
}
return points;
},
set: function(value) {
var x = that.x;
var y = that.y;
var v = that.visible;
that.dispose(true);
points = value;
if (that.shape) {
that.shape.graphics.clear();
that.sticks.graphics.clear();
that.controls.noDrag();
that.removeAllChildren();
delete that.shape;
delete that.sticks;
delete that.controls;
}
init(); // remake Squiggle
that.lockControls = _lockControls;
that.x = x;
that.y = y;
that.visible = v;
}
});
Object.defineProperty(that, 'pointsAdjusted', { // points with rotation
get: function() {
var points = [];
var point; var p; var poo;
var pObjects = that.pointObjects;
zim.loop(pObjects.length, function(i, t) {
po = pObjects[i];
p = _points[i];
if (po[0].rotation==0 && po[0].scaleX==0 && po[0].scaleY==0) { // get points
point = [
zim.decimals(p[0].x),
zim.decimals(p[0].y),
zim.decimals(p[1].x),
zim.decimals(p[1].y),
zim.decimals(p[2].x),
zim.decimals(p[2].y),
zim.decimals(p[3].x),
zim.decimals(p[3].y)
];
} else {
var lo1 = po[0].localToLocal(po[2].x, po[2].y, po[0].parent);
var lo2 = po[0].localToLocal(po[3].x, po[3].y, po[0].parent);
point = [
zim.decimals(p[0].x),
zim.decimals(p[0].y),
zim.decimals(p[1].x),
zim.decimals(p[1].y),
zim.decimals(lo1.x-p[0].x),
zim.decimals(lo1.y-p[0].y),
zim.decimals(lo2.x-p[0].x),
zim.decimals(lo2.y-p[0].y)
];
}
if (p[4] && p[4]!=="mirror") point.push(p[4])
points.push(point);
});
return points;
},
set: function(value) {
if (zon) zogy("Squiggle() - pointsAdjusted is read only")
}
});
Object.defineProperty(that, 'pointObjects', {
get: function() {
return _points;
},
set: function(value) {
if (zon) {zog("Squiggle() - pointObjects is read only - but its contents can be manipulated - use squiggle.update() after changes")}
}
});
Object.defineProperty(that, 'pointControls', {
get: function() {
return _pointControls;
},
set: function(value) {
if (zon) {zog("Squiggle() - pointControls is read only - but its contents can be manipulated - use blob.update() after changes")}
}
});
Object.defineProperty(that, 'pointCircles', {
get: function() {
return _pointCircles;
},
set: function(value) {
if (zon) {zog("Squiggle() - pointCircles is read only - but its contents can be manipulated - use blob.update() after changes")}
}
});
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// path manipulation and animating to path methods
Object.defineProperty(that, 'segmentPoints', {
get: function() {
var array = []; // array of prepared segment points
var p = that.pointsAdjusted;
zim.loop(p.length-1, function(i, t) {
var s = that.getSegmentPoint(p[i], p[i+1])
array.push(s);
});
return array;
},
set: function(value) {
if (zon) {zog("Squiggle() - segmentPoints is read only")}
}
});
Object.defineProperty(that, 'segmentRatios', {
get: function() {
var distances = []
var total = 0;
zim.loop(that.segmentPoints, function(points) {
var d = zim.distanceAlongCurve(points)
distances.push(d);
total += d;
});
var percents = [];
var totalPercents = 0;
zim.loop(distances, function (d) {
var p = d/total;
totalPercents += p;
percents.push(totalPercents);
});
return percents;
},
set: function(value) {
if (zon) {zog("Squiggle() - segmentRatios is read only")}
}
});
that.approximateBounds = function(num, showPoints) {
if (zot(num)) num = 80;
num /= that.num;
var points = that.interpolate(num, null, true, null, true);
var bounds = zim.boundsAroundPoints(points);
that.setBounds(bounds.x, bounds.y, bounds.width, bounds.height);
if (showPoints) {
if (!that.hitPathPoints) that.hitPathPoints = new zim.Container().addTo();
else that.hitPathPoints.removeAllChildren();
that.hitPathPoints.top();
for (var i=0; i= that.num-2) {
return [
[that.getSegmentPoint(p[that.num-3], p[that.num-2]),
that.getSegmentPoint(p[that.num-2], p[that.num-1])],
[that.num-3, that.num-2]
];
} else {
return [
[that.getSegmentPoint(p[index-1], p[index]),
that.getSegmentPoint(p[index], p[index+1]),
that.getSegmentPoint(p[index+1], p[index+2])],
[index-1,index,index+1]
];
}
}
that.getCurvePoint = function(ratio, segmentRatios, segmentPoints, getAngle, even) {
if (zot(ratio) || isNaN(ratio)) ratio = 0;
if (zot(segmentRatios)) segmentRatios = that.segmentRatios;
if (zot(segmentPoints)) segmentPoints = that.segmentPoints;
if (zot(getAngle)) getAngle = false;
if (zot(even)) even = false;
var percents = segmentRatios;
var segments = segmentPoints;
var afterIndex = zim.loop(percents, function (p, i) {
if (p >= ratio) return i;
});
var earlierPercent = afterIndex > 0 ? percents[afterIndex-1] : 0;
var localTotal = afterIndex > 0 ? (percents[afterIndex]-percents[afterIndex-1]):percents[afterIndex];
if (!localTotal) return undefined;
var localPercent = (ratio-earlierPercent)/localTotal;
var finalPoint = zim.pointAlongCurve(segments[afterIndex], localPercent, getAngle, true);
var finalFinalPoint = that.localToGlobal(finalPoint.x, finalPoint.y);
finalFinalPoint.angle = finalPoint.angle;
finalFinalPoint.z = afterIndex;
return !zot(finalFinalPoint) ? finalFinalPoint : undefined;
}
function proportion(p1, p2, ratio) {
return {
x:p1.x + (p2.x-p1.x)*ratio,
y:p1.y + (p2.y-p1.y)*ratio
}
}
function insertPointData(points, controls, ratios, percent, controlType, skipPoint, dataOnly, even) {
var index = points.length-1; // adjust for squiggle
var lastRatio = 0;
var currentRatio = 0;
if (percent == 100 && that.type == "Squiggle") percent = 99.99;
percent = (percent+100000)%100;
zim.loop(ratios, function (ratio, i) {
if (percent/100 < ratio) {
index = i;
currentRatio = ratio;
return true;
}
lastRatio = ratio;
});
var segment = that.segmentPoints[index];
var r = currentRatio > 0?(percent/100-lastRatio)/(currentRatio-lastRatio):0
var point = zim.pointAlongCurve(segment, r, null, even)
var newPoint = [point.x,point.y, 0, 0];
if (skipPoint) return;
if (dataOnly) {
that.interpolatedPoints.push({x:point.x, y:point.y, r:percent/100});
return;
}
if (controlType != "none") {
// calculate new handles and adjust old handles
// [controlX, controlY, circleX, circleY, rect1X, rect1Y, rect2X, rect2Y, controlType]
var startHandle = proportion(segment[0], segment[1], r);
var midPoint = proportion(segment[1], segment[2], r);
var endHandle = proportion(segment[2], segment[3], r);
var newStartHandle = proportion(startHandle, midPoint, r);
var newEndHandle = proportion(midPoint, endHandle, r);
newPoint[4] = newStartHandle.x-point.x
newPoint[5] = newStartHandle.y-point.y;
newPoint[6] = newEndHandle.x-point.x;
newPoint[7] = newEndHandle.y-point.y;
var start = that.localToLocal(startHandle.x, startHandle.y, controls[index])
points[index][6] = start.x;
points[index][7] = start.y;
var end = that.localToLocal(endHandle.x, endHandle.y, controls[(index+1)%points.length])
points[(index+1)%points.length][4] = end.x;
points[(index+1)%points.length][5] = end.y;
}
if (controlType) newPoint[8] = controlType;
points.splice(index+1, 0, newPoint);
}
this.addPoint = function(percent, controlType) {
if (zot(percent)) percent = 100;
var points = that.points;
var ratios = that.segmentRatios;
var controls = that.pointControls;
insertPointData(points, controls, ratios, percent, controlType);
that.points = points;
that.num = points.length;
return that;
}
this.addPoints = function(num, controlType, startPoint, spread, dataOnly, points, even) {
if (zot(points)) points = zim.copy(that.points);
var ratios = zim.copy(that.segmentRatios);
var lastRatio = 0;
if (dataOnly) that.interpolatedPoints = [];
// dataOnly should add points to current point too
// but can't just use current point because sometimes that is static
// like when dragging the shape or a point - it does not register until mouseup
// and things like hitTestPath need that to be dynamic
// So the below does not work:
// if (dataOnly) {
// that.interpolatedPoints = [];
// zim.loop(points, function (point, i) {
// if (!zot(startPoint) && i!=startPoint) return;
// that.interpolatedPoints.push({x:point[0], y:point[1]})
// });
// }
if (spread) var totalPoints = ratios.length*num;
zim.loop(ratios, function (ratio, j) {
if (dataOnly) insertPointData(points, that.pointControls, that.segmentRatios, lastRatio*100, controlType, !zot(startPoint) && j!=startPoint, dataOnly, even);
var numCount = spread?Math.round(totalPoints*(ratio-lastRatio)):num
var div = 1/(numCount+1);
zim.loop(numCount, function(i) {
var r = lastRatio + (ratio-lastRatio)*div*(i+1);
insertPointData(points, that.pointControls, that.segmentRatios, r*100, controlType, !zot(startPoint) && j!=startPoint, dataOnly, even);
if (!dataOnly && num > 0) that.points = points;
});
lastRatio = ratio;
});
if (dataOnly && that.type == "Squiggle") {
// changed to skipPoint false in zim 10.7.0 - not sure why it was true...
insertPointData(points, that.pointControls, that.segmentRatios, 100, controlType, false, dataOnly, even);
}
if (that.stage) that.stage.update();
that.num = points.length;
return that;
}
this.interpolate = function(num, startPoint, spread, points, even) {
if (zot(num)) num = 1;
// dataOnly will add Point to start point too
that.addPoints(num, "none", startPoint, spread, true, points, even)
return that.interpolatedPoints;
}
this.linearGradient = function(colors,ratios,x0,y0,x1,y1) {
this.linearGradientParams = Array.prototype.slice.call(arguments);
this.thicknessCommand.linearGradient(colors,ratios,x0,y0,x1,y1);
return this;
}
this.radialGradient = function(colors,ratios,x0,y0,radius0,x1,y1,radius1) {
this.radialGradientParams = Array.prototype.slice.call(arguments);
this.thicknessCommand.radialGradient(colors,ratios,x0,y0,radius0,x1,y1,radius1);
return this;
}
this.dispose = function(temp, b, disposing) {
// if (that.toggleStageEvent) that.stage.off("stagemousedown", that.toggleStageEvent);
// this.zimContainer_dispose();
// return true;
if (!that.shape) return;
that.shape.cursor = "default";
for (var i=0; i 0)
hasProp(property as String) - returns true if property exists on object else returns false
clone(exact, commands) - makes a copy of the object
exact (default false)
ZIM VEE (Pick) values are active in clones unless exact is set to true
For instance, if the object's color is [blue, green]
then its clone might be blue or green - which could be different than the original
If exact is set to true then the clone will be the color of the original object
commands (default false) makes clones with current color commands of object
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
shape - gives access to the shape of the blob
color - get and set the fill color
colorRange - if setColorRange() is used, the colorRange is a ratio (0-1) between the colors
setting the colorRange will change the color property of the shape
for instance, shape.setColorRange(blue, pink) then shape.colorRange = .5
will set the color of the shape to half way between blue and pink
shape.animate({color:red}, 1000); is a shortcut to animate the colorRange
shape.wiggle("colorRange", .5, .2, .5, 1000, 5000) will wiggle the colorRange
colorCommand - access to the CreateJS fill command for bitmap, linearGradient and radialGradient fills
eg. shape.colorCommand.linearGradient([green, blue ,green], [.2, .5, .8], 0, 0, shape.width, 0)
See: https://www.createjs.com/docs/easeljs/classes/Graphics.Fill.html
borderColor - get and set the stroke color
borderColorCommand - access to the CreateJS stroke command for bitmap, linearGradient and radialGradient strokes
See: https://www.createjs.com/docs/easeljs/classes/Graphics.Stroke.html
borderWidth - get and set the stroke size in pixels
borderWidthCommand - access to the CreateJS stroke style command (width, caps, joints, miter, ignoreScale)
See: https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeStyle.html
borderDashedCommand - access to the CreateJS stroke dashed command (segments, offset)
see https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeDash.html
stickColor - get or set the stick color of the controls - requires an update() to see changes
points - get or set the points array of the Blob in the same format as the points parameter:
a number, a shape string ("circle", "rectangle", "triangle"), a ZIM Circle, Rectangle, Triangle
or an array as follows:
[[controlX, controlY, circleX, circleY, rect1X, rect1Y, rect2X, rect2Y, controlType], [etc]]
pointsAdjusted - get points with any point rotation converted to 0 - see update(true)
pointControls - get an array of controls (a container) - use this to animate controls
pointCircles - get an array of control circles - use this to place some other object at the point
pointObjects - get an array of point objects for each point in the following format:
[[control, circle, rect1, rect2, controlType], [etc.]]
control - the container for the control that holds the circle and rectangles (also see pointControls)
circle - the control point circle (also see pointCircles)
rect1 - the first control point rectangle
rect2 - the second control point rectangle
controlType - the control type: default is "straight" (or null) and there is also "mirror", "free" and "none"
NOTE: control, circle, rect1, rect2 can be positioned or animated and controlType can be changed
NOTE: the update() method must be called if manually changing the control positions or type
NOTE: if constantly animating the controls then use a Ticker.add(function(){blob.update();})
NOTE: also see recordData(), setData(), recordPoints(), setPoints() methods for further options
addPointFactor - (default 20) used when placing new points along edge (editPoints is true)
divides the distance between points by this amount - the smaller the more accurate but also slower
addMinDistance - (default 15) edge press needs to be within this distance to add a point to the edge
segmentPoints - a read-only array of cubic Bezier points for each segment
each element is in the form of [point1, controlPoint1, controlPoint2, point2]
used internally to animate to the path and add and remove Bezier points
segmentRatios - a read-only array of cumulative ratio lengths of segments
for instance the default four points is [.25, .5, .75, 1]
used internally to animate to the path and attribute proportional time to each segment
controls - access to the container that holds the sets of controls
each control is given a read-only num property
sticks - access to the container that holds the control sticks
lastSelected - access to the last selected (or created) control container
lastSelectedIndex - the index number of the last selected controls
controlsVisible - get or set the visibility of the controls - or use showControls() and hideControls()
types - get or set the general array for the types ["mirror", "straight", "free", "none"]
changing this or removing a type will adjust the order when the user double clicks the points to change their type
this is not an array of types for each point - see the points property to access the types of each point
lockControls - Boolean to lock controls from being adjusted or not
allowToggle - Boolean to get or set clicking to show and hide controls
move - Boolean to drag or not drag Blob when controls are showing
can also set to "always" to allow movement when controls are not showing
lockControlType - Boolean to lock the type of the controls in their current state or not
onTop - get or set the onTop property
selectPoints - get or set whether points can be selected
interactive - get or set whether the shape is interactive - toggle, move, change or add controls, etc.
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
depth - for ZIM VR - the depth used to shift left and right channel and for parallax in VR - also see dep() ZIM Display method
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
keyFocus - get or set the keyboard focus on the DisplayObject - see also zim.KEYFOCUS
will be set to true if this DisplayObject is the first made or DisplayObject is the last to be used with keyboard
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
dispatches a "change" event for when the bezier controls are adjusted (pressup only or moving with keys - thanks Yui Kim for find)
if monitoring constant change is needed add a pressmove event to Blob.sets
the change event object has a transformType property with values of "move", "bezierPoint", "bezierHandle", "bezierSwitch"
dispatches "controlsshow" and "controlshide" events when clicked off and on and toggle is true
dispatches an "update" event if the points are changed or a point is added or removed
this removes all listeners on the old shape and controls
so any custom listeners on shape and controls will need to be re-applied - use the update event to do so
dispatches a "traversed" event when traverse() is done - the event object has an obj property for the traversing object
See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+53.5
zim.Blob = function(color, borderColor, borderWidth, points, radius, controlLength, controlType, lockControlType, showControls, lockControls, handleSize, allowToggle, move, dashed, onTop, stickColor, selectColor, selectPoints, editPoints, interactive, strokeObj, style, group, inherit) {
var sig = "color, borderColor, borderWidth, points, radius, controlLength, controlType, lockControlType, showControls, lockControls, handleSize, allowToggle, move, dashed, onTop, stickColor, selectColor, selectPoints, editPoints, interactive, strokeObj, style, group, inherit";
var duo; if (duo = zob(zim.Blob, arguments, sig, this)) return duo;
z_d("53.5");
this.group = group;
var DS = style===false?{}:zim.getStyle("Blob", this.group, inherit);
if (zot(radius)) radius = DS.radius!=null?DS.radius:100;
this.zimContainer_constructor(-radius,-radius,radius*2,radius*2,false);
this.type = "Blob";
if (zot(dashed)) dashed = DS.dashed!=null?DS.dashed:false;
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:null;
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:null;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = 1;
if (zot(color)) color = DS.color!=null?DS.color:(borderWidth>0?"rgba(0,0,0,0)":zim.green);
if (color.style) {this.colorCommand = color; color = "black";}
if (borderColor && borderColor.style) {this.borderColorCommand = borderColor; borderColor = "black";}
if (zot(points)) points = DS.points!=null?DS.points:4;
var num = typeof points == "number" ? points : points.length;
var controlLengthOriginal = controlLength;
if (zot(controlLength)) controlLength = DS.controlLength!=null?DS.controlLength:(radius * 4 / num);
if (zot(controlType)) controlType = DS.controlType!=null?DS.controlType:null;
var originalControlType = controlType;
if (zot(controlType)) controlType = "straight";
if (zot(lockControlType)) lockControlType = DS.lockControlType!=null?DS.lockControlType:false;
if (zot(interactive)) interactive = DS.interactive!=null?DS.interactive:true;
if (zot(showControls)) showControls = DS.showControls!=null?DS.showControls:interactive;
var _controls = showControls;
if (zot(lockControls)) lockControls = DS.lockControls!=null?DS.lockControls:!interactive;
if (zot(handleSize)) handleSize = DS.handleSize!=null?DS.handleSize:(zim.mobile()?20:10);
if (zot(allowToggle)) allowToggle = DS.allowToggle!=null?DS.allowToggle:interactive;
if (zot(move)) move = DS.move!=null?DS.move:interactive;
if (zot(stickColor)) stickColor = DS.stickColor!=null?DS.stickColor:"#111";
if (zot(selectColor)) selectColor = DS.selectColor!=null?DS.selectColor:"#fff";
if (zot(selectPoints)) selectPoints = DS.selectPoints!=null?DS.selectPoints:interactive;
this.stickColor = stickColor;
if (zot(onTop)) onTop = DS.onTop!=null?DS.onTop:true;
if (zot(editPoints)) editPoints = DS.editPoints!=null?DS.editPoints:interactive;
if (zot(strokeObj)) strokeObj = DS.strokeObj!=null?DS.strokeObj:{};
var oa = remember(color, borderColor);
function remember() {return arguments;} // for cloning PICK
color = zim.Pick.choose(color);
borderColor = zim.Pick.choose(borderColor);
var that = this;
this.interactive = interactive;
this.num = num;
this.editPoints = editPoints;
this.selectPoints = selectPoints;
this.lockControls = lockControls;
this.onTop = onTop;
this.move = move;
this.allowToggle = allowToggle;
this.lockControlType = lockControlType;
var types = this.types = ["mirror", "straight", "free", "none"];
var _points;
var _pointCircles;
var _pointControls;
var _color = color;
var _borderColor = borderColor;
var _borderWidth = borderWidth;
var shape;
var moveDownEvent;
var movePressEvent;
var moveUpEvent;
var stage;
var draggingCheck = that.move;
var min = 2; // distance within which to count as click to add point
var mapMove;
var drawShape;
var sets;
points = checkForShape(points);
function checkForShape(shape) {
if (shape=="circle" || shape == "rectangle" || shape =="triangle") {
if (shape == "circle") shape = new Circle(radius);
if (shape == "rectangle") shape = new Rectangle(radius*2,radius*2).centerReg({add:false});
if (shape == "triangle") shape = new Triangle(radius*2,radius*2,radius*2);
}
var points;
if (shape.type == "Circle" || shape.type == "Rectangle" || shape.type == "Triangle") {
var b = shape.getBounds();
if (shape.type == "Circle") {
points = 4;
controlLengthOriginal = controlLength = radius*2*.5523;
} else if (shape.type == "Rectangle") {
shape.centerReg({add:false});
points = [[b.x-b.width/2, b.y-b.height/2],[b.x+b.width/2, b.y-b.height/2],[b.x+b.width/2, b.y+b.height/2],[b.x-b.width/2, b.y+b.height/2]];
that.setBounds(b.x-b.width/2, b.y-b.height/2, b.width, b.height);
that.regX = shape.regX-b.width/2;
that.regY = shape.regY-b.height/2;
// this.rotation = shape.rotation;
// this.scaleX = shape.scaleX;
// this.scaleY = shape.scaleY;
} else if (shape.type == "Triangle") {
points = [[shape.three.x-shape.width/2, shape.three.y+shape.height/2+shape.adjusted],[shape.two.x-shape.width/2, shape.two.y+shape.height/2+shape.adjusted],[shape.one.x-shape.width/2, shape.one.y+shape.height/2+shape.adjusted]];
that.setBounds(b.x-b.width/2, b.y-b.height/2, b.width, b.height);
}
return points;
} else {
return shape;
}
}
if (typeof points == "string") {
var svgProcessor = new zim.SVGContainer();
points = svgProcessor.processPath(points);
}
if (originalControlType && typeof points != "number") {
// override controlType
loop(points, function(point) {
point[8]=originalControlType;
if (originalControlType == "none") {
point[4]=point[5]=point[6]=point[7]=0;
}
});
}
init();
function init() {
if (sets) sets.removeAllEventListeners();
if (that.selectPoints) {
that.selectedBalls = new zim.SelectionSet();
that.selectedRect1s = new zim.SelectionSet();
that.selectedRect2s = new zim.SelectionSet();
that.selectionManager = new zim.SelectionManager([
that.selectedBalls,
that.selectedRect1s,
that.selectedRect2s
], "ctrl", false);
} else {
that.selectionManager = new zim.SelectionManager(null, "ctrl");
}
num = typeof points == "number" ? points : points.length;
if (num <= 0) return;
if (zot(controlLengthOriginal)) controlLength = radius * 4 / num;
shape = that.shape = new zim.Shape({style:false}).addTo(that);
var sticks = that.sticks = new zim.Shape({style:false}).addTo(that);
if (handleSize <= 0) sticks.removeFrom();
var g = shape.graphics;
g.c();
var s = sticks.graphics;
s.c();
var ballS = handleSize/10*8;
var rectS = handleSize;
var mobile = zim.mobile();
sets = that.controls = new zim.Container({style:false}).addTo(that); // sets - a set contains a ball and two rects
if (that.interactive) sets.drag({onTop:!mobile});
_points = [];
_pointControls = [];
_pointCircles = [];
var angle, point, temp, set, rect1, rect2, ball, type, setInfo;
for (var i=0; i 0) { // no border specified or a border > 0
if (!zot(_borderColor) || !zot(_borderWidth)) { // either a border color or thickness
if (zot(_borderColor)) _borderColor = "black";
if (!that.borderColorCommand) {
that.borderColorCommand = g.s(_borderColor).command;
if (_borderColor && _borderColor.type) that.specialColor(that.borderColorCommand, _borderColor);
}
if (!that.borderWidthCommand) that.borderWidthCommand = g.ss(_borderWidth, strokeObj.caps, strokeObj.joints, strokeObj.miterLimit, strokeObj.ignoreScale).command;
if (dashed) {
if (!that.borderDashedCommand) that.borderDashedCommand = g.sd([10, 10], 5).command;
}
}
}
var set = _points[0][0];
var ballPoint = set.localToLocal(_points[0][1].x, _points[0][1].y, shape);
g.mt(ballPoint.x, ballPoint.y);
s.c().s(that.stickColor).ss(1);
var currentIndex; var nextIndex;
for (var i=0; i<_points.length; i++) {
var currentIndex = i;
var nextIndex = (i+1)%_points.length;
var set = _points[currentIndex][0];
var ball = _points[currentIndex][1];
var control1 = _points[currentIndex][2];
var control2 = _points[currentIndex][3];
var nextSet = _points[nextIndex][0];
var nextBall = _points[nextIndex][1];
var nextControl1 = _points[nextIndex][2];
var nextControl2 = _points[nextIndex][3];
var control2Point = set.localToLocal(control2.x, control2.y, shape);
var nextControl1Point = nextSet.localToLocal(nextControl1.x, nextControl1.y, shape);
var nextBallPoint = nextSet.localToLocal(nextBall.x, nextBall.y, shape);
g.bt(
control2Point.x, control2Point.y,
nextControl1Point.x, nextControl1Point.y,
nextBallPoint.x, nextBallPoint.y
);
// create the sticks
var ballPoint = set.localToLocal(ball.x, ball.y, shape);
var control1Point = set.localToLocal(control1.x, control1.y, shape);
s.mt(ballPoint.x, ballPoint.y).lt(control1Point.x, control1Point.y);
s.mt(ballPoint.x, ballPoint.y).lt(control2Point.x, control2Point.y);
}
g.cp();
g.append(that.colorCommand);
if (dashed) g.append(that.borderDashedCommand);
if (that.borderWidthCommand) g.append(that.borderWidthCommand);
if (that.borderColorCommand) g.append(that.borderColorCommand);
}
drawShape();
var startPosition;
sets.on("mousedown", function(e) {
if (that.lockControls) return;
if (that.selectPoints) that.keyFocus = true;
startPosition = {x:e.target.x, y:e.target.y};
if (e.target.rect1) { // then mousedown on ball
var ball = e.target;
ball.startX = ball.x;
ball.startY = ball.y;
ball.rect1.startX = ball.rect1.x;
ball.rect1.startY = ball.rect1.y;
ball.rect2.startX = ball.rect2.x;
ball.rect2.startY = ball.rect2.y;
} else { // mousedown on control
var rect = e.target;
rect.startX = rect.x;
rect.startY = rect.y;
var ball = rect.ball;
var index = ball.index;
var type = controlType;
if (!zot(_points[index][4])) type = _points[index][4];
if (type == "straight") {
var other = rect.other;
var dX = other.x - ball.x;
var dY = other.y - ball.y;
other.stickLength = Math.sqrt(Math.pow(dX,2) + Math.pow(dY,2));
}
}
if (that.selectPoints) {
// need to reset all start points for each control circle and rectangle moved
var currentSet = that.selectionManager.currentSet;
if (currentSet && currentSet.selections && currentSet.selections.length > 0) {
for(var i=0; i 0) {
diffX = e.target.x-e.target.startX;
diffY = e.target.y-e.target.startY;
for(var i=0; i0) {
for(var i=0; i endPercent || obj.percentComplete == 0) {
obj.stopAnimate();
e.remove();
var eventObj = new createjs.Event("traversed");
eventObj.obj = obj;
that.dispatchEvent(eventObj);
}
});
return that;
}
that.update = function(normalize) {
if (normalize) {
// located any rotated or scaled points
// and set them back to non-rotated and non-scaled
// but keep control handles at the earlier positions
// need to normalize before doing more manual updates with Beziers
// do not need to normalize if animating blob points
that.points = that.pointsAdjusted;
} else {
drawShape();
}
that.zimAnimateChanged = true;
return that;
}
// blob
if (that.move && that.interactive) shape.drag({onTop:false});
moveDownEvent = shape.on("mousedown", function(e) {
stage = e.target.stage;
startPosition = {x:shape.x, y:shape.y};
if (that.selectPoints) that.keyFocus = true;
upTop();
});
movePressEvent = shape.on("pressmove", function() {
sets.x = shape.x;
sets.y = shape.y;
sticks.x = shape.x;
sticks.y = shape.y;
});
moveUpEvent = shape.on("pressup", function() {
var moveControlCheck = (shape.x != startPosition.x || shape.y != startPosition.y);
var movePoint = shape.localToLocal(that.regX,that.regY,that.parent);
that.x = movePoint.x;
that.y = movePoint.y;
sets.x = sets.y = sticks.x = sticks.y = shape.x = shape.y = 0;
if (moveControlCheck) {
var ev = new createjs.Event("change");
ev.controlType = "move";
that.dispatchEvent(ev);
}
stage.update();
});
if (!move) stopDragging(true);
function upTop() {
if (that.onTop) {
var nc = that.parent.numChildren-1;
if (that.parent.getChildAt(nc).type == "Keyboard") nc--;
that.parent.setChildIndex(that, nc);
}
}
that.toggleEvent = that.on("mousedown", function() {
if (!that.allowToggle) return;
if (!_controls) {
that.showControls();
that.dispatchEvent("controlsshow");
}
});
that.added(function() {
that.toggleStageEvent = that.stage.on("stagemousedown", function(e) {
if (!that.allowToggle || !that.stage) return;
if (_controls && !that.hitTestPoint(e.stageX/zim.scaX, e.stageY/zim.scaY, false)) {
that.hideControls();
that.dispatchEvent("controlshide");
}
});
});
that.clickEvent = that.on("click", function() {
if (that.ctrlKey) {
setTimeout(function() { // give time for record to work if drag with ctrl down
that.clone(true).addTo(that.stage).mov(100);
if (that.allowToggle) {
that.hideControls();
that.dispatchEvent("controlshide");
}
var ev = new createjs.Event("change");
ev.controlType = "move";
that.dispatchEvent(ev);
that.stage.update();
}, 50);
}
});
that.hideControls = function() {
that.toggled = false;
sets.visible = false;
sticks.visible = false;
_controls = false;
if (that.stage) that.stage.update();
if (!that.allowToggle && that.move) stopDragging();
return that;
}
if (!_controls) that.hideControls();
that.showControls = function() {
// if call this with code then will not trigger a change event - not good for TransformManager.persist()
that.toggled = true;
sets.visible = true;
sticks.visible = true;
_controls = true;
sets.x = shape.x;
sets.y = shape.y;
sticks.x = shape.x;
sticks.y = shape.y;
that.addChildAt(shape,0); // put to bottom incase dragged
if (that.move && !that.allowToggle) startDragging();
if (that.stage) that.stage.update();
return that;
}
that.toggle = function(state) {
if (state===true) that.showControls();
else if (state===false) that.hideControls();
else if (_controls) that.hideControls();
else that.showControls();
return that;
}
that.recordData = function(toJSON) {
if (zot(toJSON)) toJSON = false;
var obj = {
type:"Blob",
index:that.parent?that.parent.getChildIndex(that):-1,
x:that.x, y:that.y,
points:that.recordPoints(),
color:that.color,
borderColor:that.borderColor,
borderWidth:that.borderWidth,
move:that.move,
toggle:that.allowToggle,
controlsVisible:_controls
}
if (toJSON) return JSON.stringify(obj);
return obj;
}
that.setData = function(data, fromJSON) {
if (zot(data)) return;
if (fromJSON) {
try{
data = JSON.parse(data);
} catch(e) {
return;
}
}
var index = data.index;
if (zot(index)) index = -1;
delete data.index;
var pointData = data.points;
if (!zot(pointData)) that.setPoints(pointData);
delete data.points;
this.num = pointData.length;
for (var d in data) {
that[d] = data[d];
}
if (that.parent) {
that.parent.setChildIndex(that, index);
}
return that;
}
that.recordPoints = function(popup) {
// _pointCircles are relative to blob but handles are relative to ball
// points is an array of [[ballX, ballY, handleX, handleY, handle2X, handle2Y, type], etc.]
if (zot(popup)) popup = false;
var points = that.points;
if (popup) {
if (!pane) {
var pane = that.pane = new zim.Pane({
displayClose:false,
container:that.stage,
width:Math.min(500, that.stage.width-20),
height:Math.min(500, that.stage.height-20),
draggable:true,
});
var textArea = that.textArea = new zim.TextArea(Math.min(400, that.stage.width-70), Math.min(400, that.stage.height-70));
textArea.centerReg(pane);
}
textArea.text = JSON.stringify(points);
pane.show();
}
return points;
}
that.setPoints = function(points) {
// adjust blob to match points passed in from recordPoints
var p;
var p2;
for (var i=0; i0?ratios[pointBefore-1]:0;
that.addPoint(100*(lastRatio+(currentRatio-lastRatio)*(closestIndex/(testNum+1))));
}
}
that.lastSelectedIndex = pointBefore+1;
that.lastSelected = that.controls.getChildAt(that.lastSelectedIndex);
that.stage.update();
}
});
// remove point
that.controlsClickEvent = that.controls.on("click", function (e) {
that.lastSelected = e.target.parent;
var index = that.lastSelectedIndex = that.controls.getChildIndex(e.target.parent);
if (!that.editPoints) return;
if (that.selectionManager.shiftKey) { // remove
removeControl(e);
}
});
function removeControl(e) {
if (e.target.type == "Circle") {
var index = that.lastSelectedIndex = that.controls.getChildIndex(e.target.parent);
if (that.controls.numChildren <= 2) return;
var points = that.points;
if (that.selectPoints) that.lastPoints = zim.copy(points);
points.splice(index, 1); // remove the point at the index
that.points = points;
that.stage.update();
that.lastSelected = that.lastSelectedIndex = null;
}
}
that.controls.hold(removeControl);
if (!_controls) that.hideControls();
that.dispatchEvent("update");
} // end of init()
function getCurrentSelected() {
var answer = [];
var currentSet = that.selectionManager.currentSet;
if (currentSet && currentSet.selections && currentSet.selections.length > 0) {
for(var i=0; i= 37 && e.keyCode <= 40) {
var currentSelected = getCurrentSelected();
if (currentSelected.length > 0) {
for(var i=0; i= 37 && e.keyCode <= 40) {
var currentSelected = getCurrentSelected();
if (currentSelected.length > 0) {
for(var i=0; i0)) value = 0;
_borderWidth = value;
if (!that.borderWidthCommand || _borderWidth == 0) drawShape();
else {
that.borderWidthCommand.width = _borderWidth;
if (dashed) {
that.borderDashedCommand.segments = [20, 10];
that.borderDashedCommand.offset = 5;
}
}
}
});
if (typeof KEYFOCUS !== typeof undefined) zim.KEYFOCUS = KEYFOCUS;
Object.defineProperty(this, 'keyFocus', {
get: function() {
return zim.KEYFOCUS == that;
},
set: function(value) {
zim.KEYFOCUS = that;
}
});
if (that.selectPoints && !zim.KEYFOCUS) setFocus();
function setFocus() {that.keyFocus = true; var d=document.activeElement; if (d) d.blur();}
Object.defineProperty(that, 'points', {
get: function() {
var points = [];
var point; var p;
for (var i=0; i<_points.length; i++) {
p = _points[i];
point = [
zim.decimals(p[0].x),
zim.decimals(p[0].y),
zim.decimals(p[1].x),
zim.decimals(p[1].y),
zim.decimals(p[2].x),
zim.decimals(p[2].y),
zim.decimals(p[3].x),
zim.decimals(p[3].y)
];
if (p[4] && p[4]!=="straight") point.push(p[4])
points.push(point);
}
return points;
},
set: function(value) {
var x = that.x;
var y = that.y;
var v = that.visible;
that.dispose(true);
points = checkForShape(value);
if (that.shape) {
that.shape.graphics.clear();
that.sticks.graphics.clear();
that.controls.noDrag();
that.removeAllChildren();
delete that.shape;
delete that.sticks;
delete that.controls;
}
that.visible = false;
init(); // remake Blob
that.lockControls = _lockControls;
that.x = x;
that.y = y;
that.visible = v;
}
});
Object.defineProperty(that, 'pointsAdjusted', { // points with rotation
get: function() {
var points = [];
var point; var p; var poo;
var pObjects = that.pointObjects;
zim.loop(pObjects.length, function(i, t) {
po = pObjects[i];
p = _points[i];
if (po[0].rotation==0 && po[0].scaleX==0 && po[0].scaleY==0) { // get points
point = [
zim.decimals(p[0].x),
zim.decimals(p[0].y),
zim.decimals(p[1].x),
zim.decimals(p[1].y),
zim.decimals(p[2].x),
zim.decimals(p[2].y),
zim.decimals(p[3].x),
zim.decimals(p[3].y)
];
} else {
var lo1 = po[0].localToLocal(po[2].x, po[2].y, po[0].parent);
var lo2 = po[0].localToLocal(po[3].x, po[3].y, po[0].parent);
point = [
zim.decimals(p[0].x),
zim.decimals(p[0].y),
zim.decimals(p[1].x),
zim.decimals(p[1].y),
zim.decimals(lo1.x-p[0].x),
zim.decimals(lo1.y-p[0].y),
zim.decimals(lo2.x-p[0].x),
zim.decimals(lo2.y-p[0].y)
];
}
if (p[4] && p[4]!=="mirror") point.push(p[4])
points.push(point);
});
return points;
},
set: function(value) {
if (zon) zogy("Blob() - pointsAdjusted is read only")
}
});
Object.defineProperty(that, 'pointObjects', {
get: function() {
return _points;
},
set: function(value) {
if (zon) {zog("Blob() - pointObjects is read only - but its contents can be manipulated - use blob.update() after changes")}
}
});
Object.defineProperty(that, 'pointControls', {
get: function() {
return _pointControls;
},
set: function(value) {
if (zon) {zog("Blob() - pointControls is read only - but its contents can be manipulated - use blob.update() after changes")}
}
});
Object.defineProperty(that, 'pointCircles', {
get: function() {
return _pointCircles;
},
set: function(value) {
if (zon) {zog("Blob() - pointCircles is read only - but its contents can be manipulated - use blob.update() after changes")}
}
});
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// path manipulation and animating to path methods
Object.defineProperty(that, 'segmentPoints', {
get: function() {
var p = that.pointsAdjusted;
var array = []; // array of prepared segment points
zim.loop(p.length, function(i, t) {
var s = that.getSegmentPoint(p[i], p[i= that.num-1) {
return [
[that.getSegmentPoint(p[that.num-2], p[that.num-1]),
that.getSegmentPoint(p[that.num-1], p[0]),
that.getSegmentPoint(p[0], p[1])],
[that.num-2,that.num-1,0]
];
} else {
var lastIndex = (index+2>=that.num)?0:index+2
return [
[that.getSegmentPoint(p[index-1], p[index]),
that.getSegmentPoint(p[index], p[index+1]),
that.getSegmentPoint(p[index+1], p[lastIndex])],
[index-1,index,index+1]
];
}
}
that.getCurvePoint = function(ratio, segmentRatios, segmentPoints, getAngle) {
if (zot(segmentRatios)) segmentRatios = that.segmentRatios;
if (zot(segmentPoints)) segmentPoints = that.segmentPoints;
if (zot(getAngle)) getAngle = false;
var percents = segmentRatios;
var segments = segmentPoints;
var afterIndex = zim.loop(percents, function (p, i) {
if (p >= ratio) return i;
});
var earlierPercent = afterIndex > 0 ? percents[afterIndex-1] : 0;
var localTotal = afterIndex > 0 ? (percents[afterIndex]-percents[afterIndex-1]):percents[afterIndex];
var localPercent = (ratio-earlierPercent)/localTotal;
var finalPoint = zim.pointAlongCurve(segments[afterIndex], localPercent, getAngle, true);
if (zot(finalPoint)) return undefined;
var finalFinalPoint = that.localToGlobal(finalPoint.x, finalPoint.y);
finalFinalPoint.angle = finalPoint.angle;
finalFinalPoint.z = afterIndex;
return !zot(finalFinalPoint) ? finalFinalPoint : undefined;
}
function proportion(p1, p2, ratio) {
return {
x:p1.x + (p2.x-p1.x)*ratio,
y:p1.y + (p2.y-p1.y)*ratio
}
}
function insertPointData(points, controls, ratios, percent, controlType, skipPoint, dataOnly, even) {
var index = points.length-1; // adjust for squiggle
var lastRatio = 0;
var currentRatio = 0;
if (percent == 100 && that.type == "Squiggle") percent = 99.99;
percent = (percent+100000)%100;
zim.loop(ratios, function (ratio, i) {
if (percent/100 < ratio) {
index = i;
currentRatio = ratio;
return true;
}
lastRatio = ratio;
});
var segment = that.segmentPoints[index];
var r = currentRatio > 0?(percent/100-lastRatio)/(currentRatio-lastRatio):0
// zog(percent)
// zog(percent/100-currentRatio/ratios.length)
// var r = currentRatio > 0?(percent/100-1/ratios.length*currentRatio)/(currentRatio-lastRatio):0
var point = zim.pointAlongCurve(segment, r, null, even)
var newPoint = [point.x,point.y, 0, 0];
if (skipPoint) return;
if (dataOnly) {
that.interpolatedPoints.push({x:point.x, y:point.y, r:percent/100});
return;
}
if (controlType != "none") {
// calculate new handles and adjust old handles
// [controlX, controlY, circleX, circleY, rect1X, rect1Y, rect2X, rect2Y, controlType]
var startHandle = proportion(segment[0], segment[1], r);
var midPoint = proportion(segment[1], segment[2], r);
var endHandle = proportion(segment[2], segment[3], r);
var newStartHandle = proportion(startHandle, midPoint, r);
var newEndHandle = proportion(midPoint, endHandle, r);
newPoint[4] = newStartHandle.x-point.x
newPoint[5] = newStartHandle.y-point.y;
newPoint[6] = newEndHandle.x-point.x;
newPoint[7] = newEndHandle.y-point.y;
var start = that.localToLocal(startHandle.x, startHandle.y, controls[index])
points[index][6] = start.x;
points[index][7] = start.y;
var end = that.localToLocal(endHandle.x, endHandle.y, controls[(index+1)%points.length])
points[(index+1)%points.length][4] = end.x;
points[(index+1)%points.length][5] = end.y;
}
if (controlType) newPoint[8] = controlType;
points.splice(index+1, 0, newPoint);
}
this.addPoint = function(percent, controlType) {
if (zot(percent)) percent = 100;
var points = that.points;
var ratios = that.segmentRatios;
var controls = that.pointControls;
insertPointData(points, controls, ratios, percent, controlType);
that.points = points;
that.num = points.length;
return that;
}
this.addPoints = function(num, controlType, startPoint, spread, dataOnly, points, even) {
if (zot(points)) points = zim.copy(that.points);
var ratios = zim.copy(that.segmentRatios);
var lastRatio = 0;
if (dataOnly) that.interpolatedPoints = [];
// dataOnly should add points to current point too
// but can't just use current point because sometimes that is static
// like when dragging the shape or a point - it does not register until mouseup
// and things like hitTestPath need that to be dynamic
// So the below does not work:
// if (dataOnly) {
// that.interpolatedPoints = [];
// zim.loop(points, function (point, i) {
// if (!zot(startPoint) && i!=startPoint) return;
// that.interpolatedPoints.push({x:point[0], y:point[1]})
// });
// }
if (spread) var totalPoints = ratios.length*num;
zim.loop(ratios, function (ratio, j) {
if (dataOnly) insertPointData(points, that.pointControls, that.segmentRatios, lastRatio*100, controlType, !zot(startPoint) && j!=startPoint, dataOnly, even);
var numCount = spread?Math.round(totalPoints*(ratio-lastRatio)):num
var div = 1/(numCount+1);
zim.loop(numCount, function(i) {
var r = lastRatio + (ratio-lastRatio)*div*(i+1);
insertPointData(points, that.pointControls, that.segmentRatios, r*100, controlType, !zot(startPoint) && j!=startPoint, dataOnly, even);
if (!dataOnly && num > 0) that.points = points;
});
lastRatio = ratio;
});
if (dataOnly && that.type == "Squiggle") insertPointData(points, that.pointControls, that.segmentRatios, 100, controlType, null, dataOnly, even);
if (that.stage) that.stage.update();
that.num = points.length;
return that;
}
this.interpolate = function(num, startPoint, spread, points, even) {
if (zot(num)) num = 1;
// dataOnly will add Point to start point too
that.addPoints(num, "none", startPoint, spread, true, points, even)
return that.interpolatedPoints;
}
this.linearGradient = function(colors,ratios,x0,y0,x1,y1) {
this.linearGradientParams = Array.prototype.slice.call(arguments);
this.colorCommand.linearGradient(colors,ratios,x0,y0,x1,y1);
return this;
}
this.radialGradient = function(colors,ratios,x0,y0,radius0,x1,y1,radius1) {
this.radialGradientParams = Array.prototype.slice.call(arguments);
this.colorCommand.radialGradient(colors,ratios,x0,y0,radius0,x1,y1,radius1);
return this;
}
this.dispose = function(temp, d, disposing) {
// if (that.toggleStageEvent) that.stage.off("stagemousedown", that.toggleStageEvent);
// this.zimContainer_dispose();
// return true
if (!that.shape) return;
that.shape.cursor = "default";
for (var i=0; i0?"rgba(0,0,0,0)":"black");
if (zot(borderWidth) || borderWidth > 0) { // no border specified or a border > 0
if (!zot(borderColor) || !zot(borderWidth)) { // either a border color or thickness
if (zot(borderColor)) borderColor = "black";
}
}
if (zot(crossAngle)) crossAngle = DS.crossAngle!=null?DS.crossAngle:0;
var crossAngleOriginal = crossAngle;
crossAngle -= 90;
if (zot(thickness)) thickness = DS.thickness!=null?DS.thickness:null;
if (zot(thicknessA)) thicknessA = DS.thicknessA!=null?DS.thicknessA:null;
if (zot(thicknessB)) thicknessB = DS.thicknessB!=null?DS.thicknessB:null;
if (zot(thickness)) {
if (zot(thicknessB) && !zot(thicknessA)) thicknessB = thicknessA;
else if (zot(thicknessA) && !zot(thicknessB)) thicknessA = thicknessB;
else thicknessB = thicknessA = 10;
} else {
if (zot(thicknessB) && !zot(thicknessA)) thicknessB = thickness-thicknessA;
else if (zot(thicknessA) && !zot(thicknessB)) thicknessA = thickness-thicknessB;
else thicknessB = thicknessA = thickness/2;
}
that.thickness = thicknessA + thicknessB; // read-only
// from now on - do not use thickness
if (zot(cross)) cross =DS.cross!=null?DS.cross:true;
if (zot(crossColors)) crossColors =DS.crossColors!=null?DS.crossColors:null;
if (!zot(crossColors) && !Array.isArray(crossColors)) crossColors = [crossColors];
if (zot(close)) close = DS.close!=null?DS.close:false;
if (zot(startX)) startX = DS.startX!=null?DS.startX:0;
if (zot(startY)) startY = DS.startY!=null?DS.startY:0;
// lengths, angles, anglesA, anglesB, anglesEnd
if (zot(lengths)) lengths = DS.lengths!=null?DS.lengths:[200];
if (!Array.isArray(lengths)) lengths = [lengths];
if (zot(angles)) angles = DS.angles!=null?DS.angles:[0];
if (!Array.isArray(angles)) angles = [angles];
if (zot(anglesA)) anglesA = DS.anglesA!=null?DS.anglesA:[10];
if (!Array.isArray(anglesA)) anglesA = [anglesA];
if (zot(anglesB)) anglesB = DS.anglesB!=null?DS.anglesB:zim.copy(anglesA);
if (!Array.isArray(anglesB)) anglesB = [anglesB];
if (zot(anglesEnd)) anglesEnd = DS.anglesEnd!=null?DS.anglesEnd:[0];
if (!Array.isArray(anglesEnd)) anglesEnd = [anglesEnd];
if (zot(strokeObj)) strokeObj = DS.strokeObj!=null?DS.strokeObj:{miterLimit:2};
if (zot(spineBorderColor)) spineBorderColor = DS.spineBorderColor!=null?DS.spineBorderColor:null;
if (zot(spineBorderWidth)) spineBorderWidth = DS.spineBorderWidth!=null?DS.spineBorderWidth:null;
if (spineBorderColor < 0 || spineBorderWidth < 0) spineBorderColor = spineBorderWidth = null;
else if (spineBorderColor!=null && spineBorderWidth==null) spineBorderWidth = 1;
if (zot(spineColor)) spineColor = DS.spineColor!=null?DS.spineColor:(spineBorderWidth>0?"rgba(0,0,0,0)":"black");
if (zot(spineDashed)) spineDashed = DS.spineDashed!=null?DS.spineDashed:null;
if (zot(spineStrokeObj)) spineStrokeObj = DS.spineStrokeObj!=null?DS.spineStrokeObj:{miterLimit:2};
if (zot(spineBorderWidth) || spineBorderWidth > 0) {
if (!zot(spineBorderColor) || !zot(spineBorderWidth)) {
if (zot(spineBorderColor)) spineBorderColor = borderColor?borderColor:"black";
}
}
if (zot(closeBorderColor)) closeBorderColor = DS.closeBorderColor!=null?DS.closeBorderColor:null;
if (zot(closeBorderWidth)) closeBorderWidth = DS.closeBorderWidth!=null?DS.closeBorderWidth:null;
if (closeBorderColor < 0 || closeBorderWidth < 0) closeBorderColor = closeBorderWidth = null;
else if (closeBorderColor!=null && closeBorderWidth==null) closeBorderWidth = 1;
if (zot(closeColor)) closeColor = DS.closeColor!=null?DS.closeColor:(closeBorderWidth>0?"rgba(0,0,0,0)":null);
if (zot(closeDashed)) closeDashed = DS.closeDashed!=null?DS.closeDashed:null;
if (zot(closeStrokeObj)) closeStrokeObj = DS.closeStrokeObj!=null?DS.closeStrokeObj:{miterLimit:2};
if (zot(closeBorderWidth) || closeBorderWidth > 0) {
if (!zot(closeBorderColor) || !zot(closeBorderWidth)) {
if (zot(closeBorderColor)) closeBorderColor = borderColor?borderColor:"black";
}
}
this.thicknessA = thicknessA;
this.thicknessB = thicknessB;
this.cross = cross;
this.close = close;
this.lengths = lengths;
this.angles = angles;
this.anglesA = anglesA;
this.anglesB = anglesB;
this.anglesEnd = anglesEnd;
this.crossColors = crossColors;
drawShape(lengths, angles, anglesA, anglesB, anglesEnd, cross, crossColors, close);
function drawShape(lengths, angles, anglesA, anglesB, anglesEnd, cross, crossColors, close) {
that.removeAllChildren();
var s = that.shape = new zim.Shape().addTo(that);
that.colorCommand = s.c().f(color).command;
if (color && color.type) that.specialColor(that.colorCommand, color);
if (zot(borderWidth) || borderWidth > 0) {
if (!zot(borderColor) || !zot(borderWidth)) {
if (zot(borderColor)) borderColor = "black";
that.borderColorCommand = s.s(borderColor).command;
if (borderColor && borderColor.type) that.specialColor(that.borderColorCommand, borderColor);
that.borderWidthCommand = s.ss(borderWidth, strokeObj.caps, strokeObj.joints, strokeObj.miterLimit, strokeObj.ignoreScale).command;
if (dashed) that.borderDashedCommand = s.sd([10, 10], 5).command;
}
}
s.mt(0,0);
if (spineBorderWidth > 0) {
var spineS = that.spineShape = new zim.Shape().addTo(that);
that.spineColorCommand = spineS.c().f(spineColor).command;
if (spineColor && spineColor.type) that.specialColor(that.spineColorCommand, spineColor);
if (zot(spineBorderWidth) || spineBorderWidth > 0) {
if (!zot(spineBorderColor) || !zot(spineBorderWidth)) {
if (zot(spineBorderColor)) spineBorderColor = "black";
that.spineBorderColorCommand = spineS.s(spineBorderColor).command;
if (spineBorderColor && spineBorderColor.type) that.specialColor(that.spineBorderColorCommand, spineBorderColor);
that.spineBorderWidthCommand = spineS.ss(spineBorderWidth, spineStrokeObj.caps, spineStrokeObj.joints, spineStrokeObj.miterLimit, spineStrokeObj.ignoreScale).command;
if (spineDashed) that.spineBorderDashedCommand = spineS.sd([10, 10], 5).command;
}
}
}
if (!zot(closeColor)) {
var closeS = that.closeShape = new zim.Shape().addTo(that);
that.closeColorCommand = closeS.c().f(closeColor).command;
if (closeColor && closeColor.type) that.specialColor(that.closeColorCommand, closeColor);
if (zot(closeBorderWidth) || closeBorderWidth > 0) {
if (!zot(closeBorderColor) || !zot(closeBorderWidth)) {
if (zot(closeBorderColor)) closeBorderColor = "black";
that.closeBorderColorCommand = closeS.s(closeBorderColor).command;
if (closeBorder && closeBorder.type) that.specialColor(that.closeBorderCommand, closeBorder);
that.closeBorderWidthCommand = closeS.ss(closeBorderWidth, closeStrokeObj.caps, closeStrokeObj.joints, closeStrokeObj.miterLimit, closeStrokeObj.ignoreScale).command;
if (closeDashed) that.closeBorderDashedCommand = closeS.sd([10, 10], 5).command;
}
}
s.mt(0,0);
}
// start values
var sX = startX;
var sY = startY;
var f2 = crossAngle;
var f = f2-180;
var tA = thicknessA;
var tB = thicknessB;
var lastAngle = angles[0];
var num = Math.max(lengths.length, angles.length, anglesA.length, anglesB.length, anglesEnd.length);
var lastB, lastC
var lastAngle = f;
var pointsA = [];
var pointsB = [];
var pointsC = [];
var points = that.points = [];
var spines = that.pinPoints = [];
zim.loop(num, function(i, t) {
var data = getSegment(i);
var cosine = Math.cos(data.a*zim.RAD);
var sine = Math.sin(data.a*zim.RAD);
var AA = new zim.Point(sX+data.A.x*cosine-data.A.y*sine, sY+data.A.x*sine+data.A.y*cosine);
var BB = new zim.Point(sX+data.B.x*cosine-data.B.y*sine, sY+data.B.x*sine+data.B.y*cosine);
var CC = new zim.Point(sX+data.C.x*cosine-data.C.y*sine, sY+data.C.x*sine+data.C.y*cosine);
var DD = new zim.Point(sX+data.D.x*cosine-data.D.y*sine, sY+data.D.x*sine+data.D.y*cosine);
pointsA.push(AA,BB);
pointsB.unshift(CC,DD);
pointsC.push([AA,BB,CC,DD]); // for cross
var FF = new zim.Point(sX+data.F.x*cosine-data.F.y*sine, sY+data.F.x*sine+data.F.y*cosine);
var EE = new zim.Point(sX+data.E.x*cosine-data.E.y*sine, sY+data.E.x*sine+data.E.y*cosine);
if (i==0) that.pinPoints.push(FF);
that.pinPoints.push(EE);
sX = EE.x;
sY = EE.y;
tA = data.tA;
tB = data.tB;
});
that.points = pointsA.concat(pointsB);
if (!cross) {
zim.loop(pointsA, function (point, i) {
if (i==0) s.mt(point.x, point.y);
else s.lt(point.x, point.y);
});
if (close) {
s.lt(pointsA[0].x, pointsA[0].y);
s.cp();
}
zim.loop(pointsB, function (point, i) {
if (i==0 && close) s.mt(point.x, point.y);
else s.lt(point.x, point.y);
});
if (close) {
s.lt(pointsB[0].x, pointsB[0].y);
}
s.cp();
} else {
zim.loop(pointsC, function (points, i) {
s .mt(points[0].x, points[0].y);
if (!zot(crossColors) && !zot(crossColors[i])) s.f(crossColors[i]).mt(points[0].x, points[0].y);
s .lt(points[1].x, points[1].y)
.lt(points[2].x, points[2].y)
.lt(points[3].x, points[3].y)
.cp();
});
if (close) {
s .mt(pointsC[pointsC.length-1][1].x, pointsC[pointsC.length-1][1].y)
.lt(pointsC[pointsC.length-1][2].x, pointsC[pointsC.length-1][2].y)
.lt(pointsC[0][3].x, pointsC[0][3].y)
.lt(pointsC[0][0].x, pointsC[0][0].y)
.cp();
}
}
if (spineS) {
zim.loop(spines, function (spine,i) {
if (i==0) spineS.mt(spine.x, spine.y);
else spineS.lt(spine.x, spine.y);
})
if (close) {
spineS.lt(spines[0].x, spines[0].y).cp();
}
}
if (!zot(closeColor)) {
zim.loop(pointsB, function (point,i) {
if (i==0) closeS.mt(point.x, point.y);
else closeS.lt(point.x, point.y);
})
if (close) {
closeS.lt(pointsB[0].x, pointsB[0].y).cp();
}
}
// segment values
function getSegment(num) {
var a = angles[num];
var d = lengths[num];
var aA = anglesA[num];
var aB = anglesB[num];
var e = anglesEnd[num];
if (crossColors) var cc = crossColors[num];
if (zot(a)) {a = lastAngle; that.angles[num] = a;}
if (zot(d)) {d = 200; that.lengths[num] = d;}
if (zot(aA)) {aA = 0; that.anglesA[num] = aA;}
if (zot(aB)) {aB = 0; that.anglesB[num] = aB;}
if (zot(e)) {e = 0; that.anglesEnd[num] = e;}
if (crossColors && zot(cc)) {cc = color; that.crossColors[num] = cc;}
e = e+90;
var e2 = 180-e;
var cosine = Math.cos((lastAngle-a)*zim.RAD);
var sine = Math.sin((lastAngle-a)*zim.RAD);
// GOAL is to find points F, A, B, C, D, E
var F = new zim.Point(0,0);
var E = new zim.Point(d,0);
if (zot(lastB)) {
var A = new zim.Point(Math.cos(f2*zim.RAD)*tA, Math.sin(f2*zim.RAD)*tA);
} else {
A = new zim.Point(lastB.x*cosine-lastB.y*sine, lastB.x*sine+lastB.y*cosine);
}
var pA = getEnd(d, A.x, A.y, aA, e2);
var B = new zim.Point(d-pA.x, -pA.y);
if (zot(lastC)) {
var D = new zim.Point(Math.cos(f*zim.RAD)*tA, Math.sin(f*zim.RAD)*tB);
} else {
var D = new zim.Point(lastC.x*cosine-lastC.y*sine, lastC.x*sine+lastC.y*cosine);
}
var pB = getEnd(d, D.x, D.y, aB, e);
var C = new zim.Point(d-pB.x, pB.y);
lastB = new zim.Point(B.x-d, B.y);
lastC = new zim.Point(C.x-d, C.y);
lastAngle = a;
// all the points, next start thickness AB
return {a:a, A:A, B:B, C:C, D:D, E:E, F:F, tA:pA.t, tB:pB.t}
}
function getEnd(dist, frontX, frontY, flare, endAngle) {
var u = endAngle-90;
var w = 90-u;
var v = 180-flare-w;
var n = Math.tan(u*zim.RAD)*frontY;
var s = dist-frontX-n;
var t1 = s/Math.sin(v*zim.RAD)*Math.sin(flare*zim.RAD);
var t2 = Math.sqrt(Math.pow(frontY,2) + Math.pow(n,2));
var t = t1 + t2;
var x = t*Math.sin(u*zim.RAD);
var y = t*Math.cos(u*zim.RAD);
return {x:x,y:y,t:t};
}
} // end makeShape
// METHODS
this.add = function(lengths, angles, anglesA, anglesB, anglesEnd, cross, crossColors, close) {
var sig = "lengths, angles, anglesA, anglesB, anglesEnd, cross, crossColors, close";
var duo; if (duo = zob(that.add, arguments, sig)) return duo;
if (!zot(cross)) that.cross = cross;
if (!zot(close)) that.close = close;
if (!zot(lengths)) {
if (!Array.isArray(lengths)) lengths = [lengths];
if (zot(that.lengths)) that.lengths = lengths;
else that.lengths = that.lengths.concat(lengths);
}
if (!zot(angles)) {
if (!Array.isArray(angles)) angles = [angles];
if (zot(that.angles)) that.angles = angles;
else that.angles = that.angles.concat(angles);
}
if (!zot(anglesA)) {
if (!Array.isArray(anglesA)) anglesA = [anglesA];
if (zot(that.anglesA)) that.anglesA = anglesA;
else that.anglesA = that.anglesA.concat(anglesA);
}
if (!zot(anglesB)) {
if (!Array.isArray(anglesB)) anglesB = [anglesB];
if (zot(that.anglesB)) that.anglesB = anglesB;
else that.anglesB = that.anglesB.concat(anglesB);
}
if (!zot(anglesEnd)) {
if (!Array.isArray(anglesEnd)) anglesEnd = [anglesEnd];
if (zot(that.anglesEnd)) that.anglesEnd = anglesEnd;
else that.anglesEnd = that.anglesEnd.concat(anglesEnd);
}
if (!zot(crossColors)) {
if (zot(that.crossColors)) {
if (zon) zogy("Flare() - must set crossColor for original object parameters");
} else {
if (!Array.isArray(crossColors)) crossColors = [crossColors];
if (zot(that.crossColors)) that.crossColors = crossColors;
else that.crossColors = that.crossColors.concat(crossColors);
}
}
that.remake();
}
this.remake = function() {
thicknessA = this.thicknessA;
thicknessB = this.thicknessB;
drawShape(that.lengths, that.angles, that.anglesA, that.anglesB, that.anglesEnd, that.cross, that.crossColors, that.close);
}
// PROPERTIES
Object.defineProperty(that, 'color', {
get: function() {
return color;
},
set: function(value) {
if (zot(value)) value = "black";
color = value;
if (value && value.type) that.specialColor(that.colorCommand, value);
else that.colorCommand.style = value;
}
});
var startColor;
var endColor;
this.setColorRange = function(color1, color2) {
if (zot(color2)) {
startColor = that.color;
endColor = color1;
} else if (zot(color1)) {
startColor = that.color;
endColor = color2;
} else {
startColor = color1;
endColor = color2;
}
return that;
}
var colorRange = 0;
Object.defineProperty(that, 'colorRange', {
get: function() {
return colorRange;
},
set: function(value) {
colorRange = value;
if (!zot(startColor) && !zot(endColor)) {
that.color = zim.colorRange(startColor, endColor, value);
}
}
});
Object.defineProperty(that, 'borderColor', {
get: function() {
return borderColor;
},
set: function(value) {
borderColor = value;
if (!that.borderColorCommand) drawShape();
else if (value && value.type) that.specialColor(that.borderColorCommand, value);
else that.borderColorCommand.style = value;
}
});
Object.defineProperty(that, 'borderWidth', {
get: function() {
return borderWidth;
},
set: function(value) {
if (!(value>0)) value = 0;
borderWidth = value;
if (!that.borderWidthCommand || borderWidth == 0) drawShape();
else {
that.borderWidthCommand.width = borderWidth;
if (dashed) {
that.borderDashedCommand.segments = [20, 10];
that.borderDashedCommand.offset = 5;
}
}
}
});
Object.defineProperty(that, 'spineColor', {
get: function() {
return spineColor;
},
set: function(value) {
if (zot(value)) value = "black";
spineColor = value;
if (!that.spineColorCommand) drawShape();
else if (value && value.type) that.specialColor(that.spineColorCommand, value);
else that.spineColorCommand.style = value;
}
});
Object.defineProperty(that, 'spineBorderColor', {
get: function() {
return spineBorderColor;
},
set: function(value) {
spineBorderColor = value;
if (!that.spineBorderColorCommand) drawShape();
else if (value && value.type) that.specialColor(that.spineBorderColorCommand, value);
else that.spineBorderColorCommand.style = value;
}
});
Object.defineProperty(that, 'spineBorderWidth', {
get: function() {
return spineBorderWidth;
},
set: function(value) {
if (!(value>0)) value = 0;
spineBorderWidth = value;
if (!that.spineBorderWidthCommand || spineBorderWidth == 0) drawShape();
else {
that.spineBorderWidthCommand.width = spineBorderWidth;
if (spineDashed) {
that.spineBorderDashedCommand.segments = [20, 10];
that.spineBorderDashedCommand.offset = 5;
}
}
}
});
Object.defineProperty(that, 'closeColor', {
get: function() {
return closeColor;
},
set: function(value) {
if (zot(value)) value = "black";
closeColor = value;
if (!that.closeColorCommand) drawShape();
else if (value && value.type) that.specialColor(that.closeColorCommand, value);
else that.closeColorCommand.style = value;
}
});
Object.defineProperty(that, 'closeBorderColor', {
get: function() {
return closeBorderColor;
},
set: function(value) {
closeBorderColor = value;
if (!that.closeBorderColorCommand) drawShape();
else if (value && value.type) that.specialColor(that.closeBorderColorCommand, value);
else that.closeBorderColorCommand.style = value;
}
});
Object.defineProperty(that, 'closeBorderWidth', {
get: function() {
return closeBorderWidth;
},
set: function(value) {
if (!(value>0)) value = 0;
closeBorderWidth = value;
if (!that.closeBorderWidthCommand || closeBorderWidth == 0) drawShape();
else {
that.closeBorderWidthCommand.width = closeBorderWidth;
if (closeDashed) {
that.closeBorderDashedCommand.segments = [20, 10];
that.closeBorderDashedCommand.offset = 5;
}
}
}
});
Object.defineProperty(that, 'pin', {
get: function() {
return pin;
},
set: function(value) {
if (!(value>0)) value = 0;
if (value > that.pinPoints.length-1) pin = 0;
pin = value;
var point = that.pinPoints[pin];
if (point) {
that.regX = point.x;
that.regY = point.y;
}
}
});
var b = zim.boundsAroundPoints(that.points);
this.setBounds(b.x, b.y, b.width, b.height);
if (!zot(pin)) that.pin = pin;
this.mouseChildren = false;
if (style!==false) zimStyleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new Flare(color, borderColor, borderWidth, crossAngleOriginal, zim.copy(thickness), zim.copy(thicknessA), zim.copy(thicknessB), pin, startX, startY, zim.copy(lengths), zim.copy(angles), zim.copy(anglesA), zim.copy(anglesB), zim.copy(anglesEnd), cross, zim.copy(crossColors), close, dashed, strokeObj, spineColor, spineBorderWidth, spineBorderColor, spineDashed, spineStrokeObj, closeColor, closeBorderWidth, closeBorderColor, closeDashed, closeStrokeObj, style, this.group, inherit));
}
}
zim.extend(zim.Flare, zim.Container, ["clone"], "zimContainer", false);
//-53.6
//
/*--
zim.MultiFlare = function(flares, pins, angles, endToEnd, style, group, inherit)
MultiFlare
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Joins multiple Flare objects in one container
at the pin points of the flares or end to end.
See also ZIM Flare and ZIM FlareBox.
NOTE: mouseChildren is turned to false for all zim Shape containers.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// a fan of legs with feet!
var flare = new Flare({lengths:[100,100,20,8],anglesA:[5,-5,60],anglesB:[5,-5,0]})
var multi = new MultiFlare().center();
loop(12, function (i) {
multi.add(flare.rot(i*360/12))
});
// or prepare flares and angles ahead of time
var flares = [];
var angles = [];
loop(12, function (i) {
flares.push(flare.clone());
angles.push(i*360/12);
});
new MultiFlare(flares, null, angles).center();
// a ring of beads using endToEnd
var flare = new Flare({crossAngle:-360/12, lengths:[50,20,5,20,50],anglesA:[5,60,0,-60,-5]})
var flares = [];
var angles = [];
loop(12, function (i) {
flares.push(flare.clone());
angles.push(i*360/12);
});
new MultiFlare(flares, null, angles, true).center();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
flares - (default null) an array of ZIM Flares objects to add - also see add() method
pins - (default null) an array of pin indexes for the flares
pins will set the registration point for each flare at whatever segment matches the pin index
angles - (default null) an array angles for the flares
endToEnd - (default false) set to true to locate each first segment point of the flare at the last segment point of the last flare
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
add(flares) - add an array of flares or a single flare to MultiFlare
add() redraws the whole flare so for many, make an array to start and pass it in as an argument
remove(flares) - remove an array of flares or a single flare to MultiFlare
remove() redraws the whole flare so for many, make an array to start and pass it in as an argument
cache(see Container docs for parameter description) - overrides CreateJS cache() and returns object for chaining
Leave parameters blank to cache bounds of shape (plus outer edge of border if borderWidth > 0)
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy of the multiFlare cloning the flares too
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
** can get and change the following properties
** see the paremeters for details
** if properties are changed call the remake() method to update the MultiFlare
flares - array
pins - array
angles - array
endToEnd - boolean
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
depth - for ZIM VR - the depth used to shift left and right channel and for parallax in VR - also see dep() ZIM Display method
mouseChildren - set to false so you do not drag the shape inside the rectangle
if you nest things inside and want to drag them, will want to set to true
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+53.7
zim.MultiFlare = function(flares, pins, angles, endToEnd, style, group, inherit) {
var sig = "flares, pins, angles, endToEnd, style, group, inherit";
var duo; if (duo = zob(zim.MultiFlare, arguments, sig, this)) return duo;
z_d("53.7");
this.zimContainer_constructor();
this.type = "MultiFlare";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
var that = this;
if (zot(flares)) flares = DS.flares!=null?DS.flares:[];
if (!Array.isArray(flares)) flares = [flares];
// pins, angles, endToEnd
if (zot(pins)) pins = DS.pins!=null?DS.pins:null;
if (zot(angles)) angles = DS.angles!=null?DS.angles:null;
if (zot(endToEnd)) endToEnd = DS.endToEnd!=null?DS.endToEnd:false;
that.flares = flares;
that.pins = pins;
that.angles = angles;
that.endToEnd = endToEnd;
that.mouseChildren = false;
that.add = function(f, clone) {
if (zot(f)) return that;
if (zot(clone)) clone = true;
if (!Array.isArray(f)) f = [f];
zim.loop(f, function (flare) {
if (clone) that.flares.push(flare.clone());
else that.flares.push(flare);
});
that.remake();
if (that.stage) that.stage.update();
return that;
}
that.remove = function(f) {
if (zot(f)) return that;
if (!Array.isArray(f)) f = [f];
zim.loop(f, function (flare) {
var index = that.flares.indexOf(flare);
if (index>=0) that.flares.splice(index, 1);
})
that.remake();
if (that.stage) that.stage.update();
return that;
}
that.remake = function () {
that.removeAllChildren();
zim.loop(that.flares, function (flare, i) {
if (pins && !zot(pins[i])) flare.pin = pins[i];
if (angles && !zot(angles[i])) flare.rotation = angles[i];
flare.addTo(that);
that.flares.push(flare);
if (endToEnd) {
if (i>0) {
var last = flares[i-1];
var lastPoint = last.pinPoints[last.pinPoints.length-1];
var point1 = last.localToLocal(lastPoint.x, lastPoint.y, that);
var firstPoint = flare.pinPoints[0];
var point2 = flare.localToLocal(firstPoint.x, firstPoint.y, that);
flare.mov(point1.x-point2.x, point1.y-point2.y);
}
}
});
}
that.remake();
if (style!==false) zimStyleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new MultiFlare(copy(flares,true), copy(pins), copy(angles), endToEnd, style, this.group, inherit));
}
}
zim.extend(zim.MultiFlare, zim.Container, ["clone"], "zimContainer", false);
//-53.7
/*--
zim.FlareBox = function(width, height, color, borderColor, borderWidth, flares, corners, pins, style, group, inherit)
FlareBox
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Makes a Rectangle with ZIM Flare objects positioned around edges and corners.
Pass in an array of Flare objects or a MultiFlare
FlareBox places flares at specified corner indexes depending on flare pin index.
See also ZIM Flare and ZIM MultiFlare.
A FlareBox can be used as a backing and rollBacking for buttons and other components
to create exciting borders inspired by the tail lights of 2020 automibiles.
See: https://zimjs.com/ten/flare.html
NOTE: mouseChildren is turned to false for all zim Shape containers.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var border1 = new Flare({
thickness:6,
angles:[0,90], // to the right then down
lengths:[60,90],
anglesA:[3,-1.5], // flare angles
anglesEnd:[45,0], // 0 is optional
color:white,
pin:1 // pin at flare corner
});
var border2 = new Flare({
thickness:25,
angles:[0,90], // to right then down
lengths:[50,50],
anglesA:[-2,2], // anglesB will mirror these if not provided
anglesEnd:[45],
color:dark,
pin:1 // pin at flare corner
});
// put both flares at left top corner 0
// they each have pin of 1 so
// the rotation is (0-1)*90 = -90 (counter clockwise)
// they were to the right and down
// now they are up and to the right
var flareBox = new FlareBox(220, 100, blue, dark, 3, [border1, border2], [0,0])
.centerReg();
// clone the flares for the rollover FlareBox
// put the first flare at corner 2
// the rotation becomes (2-1)*90 = 90 (clockwise)
// it was built to go to the right and down
// now it is going down and to the left
var flareBoxOver = new FlareBox(220, 100, green, dark, 3, [border1.clone(), border2.clone()], [2,0])
.centerReg({add:false});
// use the flareBoxes as backings
var button = new Button({
width:flareBox.width,
height:flareBox.height,
backing:flareBox,
rollBacking:flareBoxOver
}).center();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - (default 220) the width of the rectangle about which the Flare objects are placed
this is a little larger than the ZIM Button default width
height - (default 80) the height of the rectangle about which the Flare objects are placed
this is a little larger than the ZIM Button default height
color - (default "black") the fill color as any CSS color including "rgba()" for alpha fill (set a to 0 for tranparent fill)
borderColor - (default null) the stroke color
borderWidth - (default 1 if stroke is set) the size of the stroke in pixels
flares - (default null) an array of ZIM Flare objects or a single flare or a ZIM MultiFlare
corners - (default [0]) an array of corner indexes to place the pin points of the ZIM Flare objects
corner indexes are:
0 - LEFT TOP
1 - RIGHT TOP
2 - RIGHT BOTTOM
3 - LEFT BOTTOM
pins - (default null) an array of pins of the ZIM Flare objects
The pin index can be set on the Flare or through the MultiFlare or here in the FlareBox
The pin is also the registration point of the flare so the flare will be placed at the corner at its pin
FlareBox will also automatically rotate the flares with this formula:
flare.rotation = (corner-pin)*90
This formula allows for easy setting of angles on corners
See the Button at https://zimjs.com/ten/flare.html
This can be overridden by setting the flare rotation after the FlareBox is created
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
setColorRange(color1, color2) - set a color range for shape - used by colorRange property - returns obj for chaining
if one color is used, the current color is used and color1 is the second color in the range
cache(see Container docs for parameter description) - overrides CreateJS cache() and returns object for chaining
Leave parameters blank to cache bounds of shape (plus outer edge of border if borderWidth > 0)
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy of the flareBox and clone flares as well
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
multiFlare - gives access to the ZIM Multiflare object
this is made automatically by FlareBox if an array of flares was used
flares - an array of flares that belong to the multiFlare
backing - gives access to the rectangle backing shape
color - get and set the fill color of the backing shape
colorRange - if setColorRange() is used, the colorRange is a ratio (0-1) between the colors
setting the colorRange will change the color property of the backing shape
for instance, shape.setColorRange(blue, pink) then shape.colorRange = .5
will set the color of the shape to half way between blue and pink
shape.animate({color:red}, 1000); is a shortcut to animate the colorRange
shape.wiggle("colorRange", .5, .2, .5, 1000, 5000) will wiggle the colorRange
borderColor - get and set the stroke color
borderWidth - get and set the stroke size in pixels
borderDashedCommand - access to the CreateJS stroke dashed command (segments, offset)
see https://www.createjs.com/docs/easeljs/classes/Graphics.StrokeDash.html
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
depth - for ZIM VR - the depth used to shift left and right channel and for parallax in VR - also see dep() ZIM Display method
mouseChildren - set to false so you do not drag the shape inside the rectangle
if you nest things inside and want to drag them, will want to set to true
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+53.8
zim.FlareBox = function(width, height, color, borderColor, borderWidth, flares, corners, pins, style, group, inherit) {
var sig = "width, height, color, borderColor, borderWidth, flares, corners, pins, style, group, inherit";
var duo; if (duo = zob(zim.FlareBox, arguments, sig, this)) return duo;
z_d("53.8");
this.group = group;
var DS = style===false?{}:zim.getStyle("FlareBox", this.group, inherit);
if (zot(width)) width = DS.width!=null?DS.width:220;
if (zot(height)) height = DS.height!=null?DS.height:80;
this.zimContainer_constructor(width, height);
this.type = "FlareBox";
var that = this;
this.mouseChildren = false;
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:null;
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:null;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = 1;
if (zot(color)) color = DS.color!=null?DS.color:(borderWidth>0?"rgba(0,0,0,0)":"black");
if (zot(borderWidth) || borderWidth > 0) { // no border specified or a border > 0
if (!zot(borderColor) || !zot(borderWidth)) { // either a border color or thickness
if (zot(borderColor)) borderColor = "black";
}
}
if (zot(flares)) flares = DS.flares!=null?DS.flares:null;
if (zot(corners)) corners = DS.corners!=null?DS.corners:null;
if (zot(pins)) pins = DS.pins!=null?DS.pins:null;
that.backing = new Rectangle(width, height, color, borderColor, borderWidth).addTo(this);
if (zot(flares)) return;
if (flares.type != "MultiFlare") {
if (!Array.isArray(flares)) {
if (flares.type != "Flare") return;
flares = [flares];
}
flares = new MultiFlare(flares, pins);
}
flares.addTo(that);
that.multiFlare = flares;
that.flares = that.multiFlare.flares;
flares.loop(function(flare, i) {
if (pins && !zot(pins[i])) flare.pin = pins[i];
else if (zot(flare.pin)) flare.pin = 0;
if (corners && !zot(corners[i])) flare.corner = corners[i];
else if (zot(flare.corner)) flare.corner = 0;
if (flare.corner==1) {
flare.loc(width,0);
} else if (flare.corner==2) {
flare.loc(width,height);
} else if (flare.corner==3) {
flare.loc(0,height);
} else {
flare.loc(0,0);
}
flare.rot((flare.corner-flare.pin)*90);
});
if (style!==false) zimStyleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new FlareBox(width, height, color, borderColor, borderWidth, copy(flares,true), copy(corners), copy(pins), style, this.group, inherit));
}
}
zim.extend(zim.FlareBox, zim.Container, ["clone"], "zimContainer", false);
//-53.8
// SUBSECTION COMPONENTS
/*--
zim.Label = function(text, size, font, color, rollColor, shadowColor, shadowBlur, align, valign, lineWidth, lineHeight, fontOptions, backing, outlineColor, outlineWidth, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backgroundDashed, padding, paddingHorizontal, paddingVertical, shiftHorizontal, shiftVertical, rollPersist, labelWidth, labelHeight, maxSize, style, group, inherit)
Label
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Makes a label - wraps the createjs Text object.
Can use with Button, CheckBox, RadioButtons and Pane.
Text seems to come in different sizes so we do our best.
Have tended to find that left and alphabetic are most consistent across browsers.
Custom fonts loaded through css can be used as well.
NOTE: can wrap text at given width using lineWidth parameter.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var label = new Label("Hello");
label.center(stage); // adds label to and centers on the stage
var label = new Label({
text:"CLICK",
size:100,
font:"courier",
color:"white",
rollColor:"red",
fontOptions:"italic bold"
});
stage.addChild(label);
label.x = label.y = 100;
label.on("click", function(){zog("clicking");});
END EXAMPLE
EXAMPLE
STYLE = {font:"courier"};
new Label("Hi Courier").center(); // will be courier not arial
STYLE = {text:"YAY!", color:"Red"};
new Label().center().mov(0,100); // will say YAY! in red arial font
new Label("Hello").center().mov(0,200); // will say Hello in red arial
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
** supports VEE - parameters marked with ZIM VEE mean a zim Pick() object or Pick Literal can be passed
Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
text |ZIM VEE| - String for the the text of the label
size - (default 36) the size of the font in pixels
font - (default arial) the font or list of fonts for the text
color - (default "black") color of font (any CSS color)
rollColor - (default color) the rollover color of the font
shadowColor - (default -1) for no shadow - set to any css color to see
shadowBlur - (default 14) if shadow is present
align - ((default "left") text registration point alignment also "center" and "right"
valign - (default "top") vertical registration point alignment alse "middle / center", "bottom"
lineWidth - (default false) for no wrapping (use \n) Can set to number for wrap
lineHeight - (default getMeasuredLineHeight) set to number to adjust line height
fontOptions - (default null) css VALUES as a single string for font-style font-variant font-weight
eg. "italic bold small-caps" or just "italic", etc.
backing - (default null) a Display object for the backing of the label (eg. Shape, Bitmap, Container, Sprite)
the backing most likely should be centerReg() ie. backing:new Rectangle(200,50,yellow).centerReg()
see ZIM Pizzazz module for a fun set of Shapes like Boomerangs, Ovals, Lightning Bolts, etc.
outlineColor - (default null - or black if outlineWidth set) - the color of the outline of the text
outlineWidth - (default null - or (size*.2) if outlineColor set) - the thickness of the outline of the text
backgroundColor - (default null) set to CSS color to add a rectangular color around the label
The background color will change size to match the text of the label
Note: the backgroundColor is different than a backing which can be any Display Object
and background parameters are ignored if a backing parameter is set
backgroundBorderColor - (default null) the background stroke color
backgroundBorderWidth - (default null) thickness of the background border
corner - (default 0) the round of corner of the background if there is one
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
backgroundDashed - (default null) set to true for dashed background border (if backgroundBorderColor or backgroundBorderWidth set)
padding - (default 10 if backgroundColor set) places the border this amount from text (see paddingHorizontal and paddingVertical)
padding parameters are ignored if there is no backgroundColor set (also ignored if a backing parameter is set)
paddingHorizontal - (default padding) places border out at top bottom
paddingVertical - (default padding) places border out at left and right
shiftHorizontal - (default 0) move the label (CreateJS Text) inside the Label container horizontally
shiftVertical - (default 0) move the label (CreateJS Text) inside the Label container vertically
rollPersist - (default false) set to true to maintain rollover stage as long as mousedown or press is activated (used by Buttons)
labelWidth - (default null) the same as the lineWidth - the text will wrap at the labelWidth (added to match labelHeight)
labelHeight - (default null) the height of the text - setting this will probably alter the font size - so the size parameter is overwritten
for labelHeight to work, the labelWidth must also be set
using labelWidth and labelHeight together allow you to fit as much text into specified width and height dimensions
maxSize - (default null) set to limit the font size when using labelWidth and labelHeight
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
setColorRange(color1, color2) - set a color range for label - used by colorRange property - returns obj for chaining
if one color is used, the current color is used and color1 is the second color in the range
showRollColor(visible) - default true to show roll color (used internally)
cache(see Container docs for parameter description) - overrides CreateJS cache() and returns object for chaining
Leave parameters blank to cache bounds of shape (plus outer edge of border if borderWidth > 0)
hasProp(property as String) - returns true if property exists on object else returns false
clone(exact) - makes a copy with properties such as x, y, etc. also copied
exact (default false) ZIM VEE (Pick) values are active in clones unless exact is set to true
For instance, if the object's color is [blue, green]
then its clone might be blue or green - which could be different than the original
If exact is set to true then the clone will be the color of the original object
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
label - references the CreateJS Text object of the label
text - references the text property of the CreateJS Text object
size - the font size of the Label (without px)
paddingHorizontal - read-only value for paddingHorizontal of label
note - no padding property - that gets split into paddingHorizontal and paddingVertical
paddingVertical - read-only value for paddingVertical of label
color - gets or sets the label text color
backgroundColor - gets or sets the label background color
colorRange - if setColorRange() is used, the colorRange is a ratio (0-1) between the colors
setting the colorRange will change the color property of the label
for instance, label.setColorRange(blue, pink) then label.colorRange = .5
will set the color of the label to half way between blue and pink
label.animate({color:red}, 1000); is a shortcut to animate the colorRange
label.wiggle("colorRange", .5, .2, .5, 1000, 5000) will wiggle the colorRange
rollColor - gets or sets the label rollover color
labelWidth - the width at which the text wraps
labelHeight - setting this and labelWidth will change the font size to fit within the specified dimensions
outlineLabel - reference to the outline CreateJS Text object if there is an outline
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
depth - for ZIM VR - the depth used to shift left and right channel and for parallax in VR - also see dep() ZIM Display method
backing - access to backing object
background - access to background Rectangle if backgroundColor is set
enabled - default is true - set to false to disable
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
OPTIMIZED
This component is affected by the general OPTIMIZE setting (default is false)
if set to true, you will have to stage.update() after setting certain properties
EVENTS
See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+54
zim.Label = function(text, size, font, color, rollColor, shadowColor, shadowBlur, align, valign, lineWidth, lineHeight, fontOptions, backing, outlineColor, outlineWidth, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backgroundDashed, padding, paddingHorizontal, paddingVertical, shiftHorizontal, shiftVertical, rollPersist, labelWidth, labelHeight, maxSize, style, group, inherit) {
var sig = "text, size, font, color, rollColor, shadowColor, shadowBlur, align, valign, lineWidth, lineHeight, fontOptions, backing, outlineColor, outlineWidth, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backgroundDashed, padding, paddingHorizontal, paddingVertical, shiftHorizontal, shiftVertical, rollPersist, labelWidth, labelHeight, maxSize, style, group, inherit";
var duo; if (duo = zob(zim.Label, arguments, sig, this)) return duo;
z_d("54");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "Label";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(text)) text=DS.text!=null?DS.text:"LABEL";
if (zot(size)) size=DS.size!=null?DS.size:36;
if (zot(font)) font=DS.font!=null?DS.font:"arial"; // arial unless manually set
if (zot(color)) color=DS.color!=null?DS.color:"black";
if (zot(fontOptions)) fontOptions=DS.fontOptions!=null?DS.fontOptions:"";
var oa = remember(text, size, font, color, fontOptions);
function remember() {return arguments;}
text = zim.Pick.choose(text);
var emptyText = false;
if (text === "") {
text = " ";
emptyText = true;
}
size = zim.Pick.choose(size);
font = zim.Pick.choose(font);
color = zim.Pick.choose(color);
fontOptions = zim.Pick.choose(fontOptions);
if (zot(rollColor)) rollColor=DS.rollColor!=null?DS.rollColor:color;
if (zot(shadowColor) || shadowColor=="ignore") shadowColor=(DS.shadowColor!=null&&shadowColor!="ignore")?DS.shadowColor:-1;
if (zot(shadowBlur) || shadowBlur=="ignore") shadowBlur=(DS.shadowBlur!=null&&shadowBlur!="ignore")?DS.shadowBlur:14;
if (zot(align)) align=DS.align!=null?DS.align:"left";
if (zot(valign)) valign=DS.valign!=null?DS.valign:"top";
if ((!zot(outlineColor) || !zot(DS.outlineColor)) && zot(outlineWidth)) outlineWidth = DS.outlineWidth!=null?DS.outlineWidth:Math.round(size*.2);
if ((!zot(outlineWidth) || !zot(DS.outlineWidth)) && zot(outlineColor)) outlineColor = DS.outlineColor!=null?DS.outlineColor:"#000000";
if (zot(outlineWidth)) outlineWidth = DS.outlineWidth!=null?DS.outlineWidth:0;
if (zot(backgroundColor) || backgroundColor=="ignore") backgroundColor = (DS.backgroundColor!=null&&backgroundColor!="ignore")?DS.backgroundColor:null;
if (zot(padding) || padding=="ignore") padding = (DS.padding!=null&&padding!="ignore")?DS.padding:10;
if (zot(paddingHorizontal)) paddingHorizontal = DS.paddingHorizontal!=null?DS.paddingHorizontal:padding;
if (zot(paddingVertical)) paddingVertical = DS.paddingVertical!=null?DS.paddingVertical:padding;
if (zot(shiftHorizontal)) shiftHorizontal = DS.shiftHorizontal!=null?DS.shiftHorizontal:0;
if (zot(shiftVertical)) shiftVertical = DS.shiftVertical!=null?DS.shiftVertical:0;
if (zot(lineWidth)) lineWidth = DS.lineWidth!=null?DS.lineWidth:null;
if (zot(lineHeight)) lineHeight = DS.lineHeight!=null?DS.lineHeight:null;
if (zot(backing) || backing=="ignore") backing = (DS.backing!=null&&backing!="ignore")?DS.backing.clone():null;
if (zot(rollPersist)) rollPersist = DS.rollPersist!=null?DS.rollPersist:false;
if (DS.labelWidth!=null) lineWidth = DS.labelWidth;
if (!zot(labelWidth)) lineWidth = labelWidth;
if (align == "middle") align = "center";
if (zot(labelHeight)) labelHeight = DS.labelHeight!=null?DS.labelHeight:null;
if (zot(maxSize)) maxSize = DS.maxSize!=null?DS.maxSize:null;
size = maxSize?Math.min(size, maxSize):size;
var retina = (typeof zimDefaultFrame!="undefined"&&zimDefaultFrame.retina);
var that = this;
this.mouseChildren = false;
this.paddingVertical = paddingVertical;
this.paddingHorizontal = paddingHorizontal;
var obj = this.label = new createjs.Text(String(text), fontOptions + " " + size + "px " + font, color);
obj.textAlign = align;
obj.lineWidth = lineWidth;
obj.lineHeight = lineHeight;
obj.textBaseline = "alphabetic";
if (outlineWidth > 0) {
var obj2 = this.outlineLabel = obj.clone();
obj2.color = outlineColor;
obj2.outline = outlineWidth;
}
if (shadowColor != -1 && shadowBlur > 0) obj.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
this.addChild(obj);
var backingPlaced = false;
if (zot(backing) && zot(backgroundColor)) {
var hitArea = new createjs.Shape();
that.hitArea = hitArea;
}
function setSize() {
var b = obj.getBounds();
var yAdjust;
if (valign == "baseline") {
yAdjust = b.y;
} else if (valign == "top") {
obj.y = size-size/6;
// if (!retina && obj2) obj2.y = size-size/6;
yAdjust = 0;
} else if (valign == "center" || valign == "middle") {
yAdjust = - b.height / 2;
obj.y = size*.3;
// if (!retina && obj2) obj2.y = size*.3;
} else { // bottom align
yAdjust = -b.height;
}
// if (valign!="baseline" && obj2) obj2.y -= size*.06/(valign=="center"?2:1);
that.setBounds(b.x, yAdjust, DS.width?DS.width-padding*2:b.width, DS.height?DS.height-padding*2:b.height);
if (that.hitArea) that.hitArea.graphics.c().f("black").r(that.getBounds().x, that.getBounds().y, that.getBounds().width, that.getBounds().height);
if (valign == "center" || valign == "middle") {
zim.pos(obj, null, 0);
zim.mov(obj, 0, 1);
}
if (backing) {
if (backingPlaced) setBackBounds();
} else if (!zot(backgroundColor)) {
setBackground();
}
function setBackground() {
that.removeChild(that.background);
that.background = new zim.Rectangle(
that.getBounds().width+paddingHorizontal*2, that.getBounds().height+paddingVertical*2,
backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backgroundDashed, null, false
);
zim.center(that.background, that, 0);
that.setBounds(that.background.x, that.background.y, that.background.width, that.background.height);
}
if (valign != "baseline" && !retina) obj.y += size/32; //32; // backing often on capital letters without descenders - was /16
finalShift();
}
setSize();
if (!zot(backing)) {
if (backing.type == "Pattern") {
that.backing = new zim.Container(that.width+paddingHorizontal*2, that.height+paddingVertical*2, null, null, false).centerReg(null, null, false);
if (shadowColor != -1 && shadowBlur > 0) {
var shadowRect = new zim.Rectangle(that.width+paddingHorizontal*2-2, that.height+paddingVertical-2, "#666", null, null, corner, null, null, false).center(that.backing);
shadowRect.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
}
var mask = new zim.Rectangle(that.width+paddingHorizontal*2, that.height+paddingVertical*2, backgroundColor, null, null, corner, null, null, false).addTo(that.backing);
backing.centerReg(mask);
backing.setMask(mask);
that.backing.pattern = backing;
} else {
that.backing = backing;
}
that.backing.center(that, 0);
backing = that.backing;
setBackBounds();
backingPlaced = true;
}
function setBackBounds() {
var bb = backing.boundsToGlobal()
var bbb = that.boundsToGlobal(bb, true);
that.setBounds(bbb.x, bbb.y, bbb.width, bbb.height);
}
function finalShift() {
zim.pos(obj, (align=="left"||align=="right")?(backing||that.background?paddingHorizontal:0):null, (valign=="top"||valign=="baseline"||valign=="bottom")?(backing||that.background?paddingVertical:0):null, align=="right", valign=="bottom");
obj.x += shiftHorizontal;
obj.y += shiftVertical;
}
finalShift();
function setOutline() {
if (obj2) {
obj2.x = obj.x;
obj2.y = obj.y;
that.addChildAt(obj2,that.background?1:0);
}
}
setOutline();
Object.defineProperty(that, 'text', {
get: function() {
var t = (obj.text == " " && emptyText) ? "" : obj.text;
return t;
},
set: function(value) {
emptyText = false;
if (value === "") {
value = " ";
emptyText = true;
}
obj.text = String(value);
if (obj2) obj2.text = String(value);
setSize();
if (!zot(lineWidth) && !zot(labelHeight)) {
fitText();
if (obj2) setOutline();
}
}
});
Object.defineProperty(that, 'size', {
get: function() {
return size;
},
set: function(value) {
size = maxSize?Math.min(value, maxSize):value;
var text = this.label.font;
// var reg = text.match(/^(\D*|.*\s)(\d\.?\d*)+px(.*)$/i);
var reg = text.match(/^(.*\s)(\d*\.?\d*)+px(.*)$/i);
if (!reg) return;
this.label.font = reg[1] + value + "px" + reg[3];
if (obj2) obj2.font = reg[1] + value + "px" + reg[3];
setSize();
}
});
Object.defineProperty(that, 'color', {
get: function() {
return color;
},
set: function(value) {
if (rollColor == color) rollColor = value;
color = value;
obj.color = color;
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
var startColor;
var endColor;
this.setColorRange = function(color1, color2) {
if (zot(color2)) {
startColor = that.color;
endColor = color1;
} else if (zot(color1)) {
startColor = that.color;
endColor = color2;
} else {
startColor = color1;
endColor = color2;
}
return that;
}
var _colorRange = 0;
Object.defineProperty(that, 'colorRange', {
get: function() {
return _colorRange;
},
set: function(value) {
_colorRange = value;
if (!zot(startColor) && !zot(endColor)) {
that.color = zim.colorRange(startColor, endColor, value);
}
}
});
Object.defineProperty(that, 'backgroundColor', {
get: function() {
return backgroundColor;
},
set: function(value) {
backgroundColor = value;
if (that.background) {
that.background.color = value;
} else if (that.backing) {
that.backing.color = value;
} else {
setBackground();
}
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
Object.defineProperty(that, 'outlineColor', {
get: function() {
return outlineColor;
},
set: function(value) {
outlineColor = value;
if (obj2) obj2.color = outlineColor;
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
Object.defineProperty(that, 'rollColor', {
get: function() {
return rollColor;
},
set: function(value) {
rollColor = value;
}
});
this._enabled = true;
Object.defineProperty(that, 'enabled', {
get: function() {
return that._enabled;
},
set: function(value) {
zenable(that, value);
obj.color = color;
that.mouseChildren = false;
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
this.showRollColor = function(yes) {
if (zot(yes)) yes = true;
if (yes) {
obj.color = rollColor;
} else {
obj.color = color;
}
if (that.stage) that.stage.update();
return that;
}
this.mouseoverEvent = this.on("mouseover", function(e) {if (that.showRollColor) that.showRollColor();});
this.mouseoutEvent = this.on("mouseout", function(e) {if (!that.rollPersist) that.showRollColor(false);});
this.pressupEvent = this.on("pressup", function(e) {if (that.rollPersist) that.showRollColor(false);});
Object.defineProperty(that, 'labelWidth', {
get: function() {
return lineWidth;
},
set: function(value) {
if (value > 0) {
lineWidth = value;
that.label.lineWidth = value;
if (obj2) obj2.lineWidth = value;
}
if (labelHeight) fitText();
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
Object.defineProperty(that, 'labelHeight', {
get: function() {
return labelHeight;
},
set: function(value) {
if (value > 0) labelHeight = value;
if (lineWidth) fitText();
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
if (!zot(lineWidth) && !zot(labelHeight)) {
fitText();
}
function fitText() {
that.size = 200;
var count = 0;
while(lineHeight < labelHeight / 2 && (that.height > labelHeight || that.width > lineWidth)) {
// while(that.height > labelHeight || that.width > lineWidth) { // ami Aug 2019
count++;
that.size = that.size/2;
if (count>50) break;
}
count = 0;
while(that.height <= labelHeight && that.width <= lineWidth) {
count++;
that.size = Math.ceil(that.size + 1);
if (count>50) break;
}
that.size = that.size - 1;
setOutline();
}
zimStyleTransforms(this, DS)
this.clone = function(exact) {
return that.cloneProps(new zim.Label((exact||!zim.isPick(oa[0]))?that.text:oa[0], (exact||!zim.isPick(oa[1]))?size:oa[1], (exact||!zim.isPick(oa[2]))?font:oa[2], (exact||!zim.isPick(oa[3]))?color:oa[3], rollColor, shadowColor, shadowBlur, align, valign, lineWidth, lineHeight, (exact||!zim.isPick(oa[4]))?fontOptions:oa[4],
!zot(backing)?backing.clone(exact):null, outlineColor, outlineWidth, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backgroundDashed, padding, paddingHorizontal, paddingVertical, shiftHorizontal, shiftVertical, rollPersist, labelWidth, labelHeight, maxSize, style, this.group, inherit));
}
}
zim.extend(zim.Label, zim.Container, "clone", "zimContainer");
//-54
/*--
zim.LabelOnPath = function(label, path, percentAngle, percents, showPath, allowToggle, interactive, onTop, style, group, inherit)
LabelOnPath
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Makes a label along a path of a Squiggle or Blob - which can be interactive, fixed, toggled or hidden
A list of percentages for where the letters are can be provided to move around letters
See: https://zimjs.com/explore/labelonpath.html
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var lop = new LabelOnPath({
label:"Hello World",
// label:new Label({text:"JELLO JIGGLES!", size:50}),
// path:new Blob(),
// path:new Squiggle({
// color:lighter,
// thickness:4,
// points:[[0,75,0,0,-100,200,100,-200],[300,75,0,0,-100,200,100,-200]]
// }).transformPoints("scaleX",2).transformPoints("rotation",0),
percentAngle:100, // default
showPath:false, // default
allowToggle:true, // default
interactive:true, // default
onTop:false // default
}).center();
zog(lop.text)
frame.on("keydown", function () {
// shows percent spacing of letters along path
// could pass [results] in as an array to percents parameter of LabelOnPath
zog(lop.percents.toString());
// uncomment to record the path
// could pass this in as the points parameter to start with a given path
// lop.path.recordPoints(true);
});
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
label - (default "Label on Path") a String or a ZIM Label
can set any label properties such as color, size, font, etc. on the label passed in
path - (default new Squiggle()) a ZIM Squiggle or ZIM Blob
can set any properties such as color, points, etc. on the shape passed in
percentAngle - (default 100) from 0-100 (or beyond in either direction) as to how much to tilt the letters
percents - (default null) an array of percentage locations of the letters along the line - should match number of letters
showPath - (default true) Boolean to show path at start
allowToggle - (default true) Boolean to allow user to toggle path off and on
interactive - (default true) Boolean to allow user to change path with controls, drag or add and remove points
can also set these individually on the path
onTop - (default false) - Boolean to set path on top when dragged
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
toggle(state) - leave off state to toggle path to opposite state. Use true to hide and false to show - returns object for chaining
hidePath() - hides path - returns object for chaining
showPath() - shows path - returns object for chaining
resize() - if not interactive, call this to update the text on the path - returns object for chaining
cache(see Container docs for parameter description) - overrides CreateJS cache() and returns object for chaining
Leave parameters blank to cache bounds of shape (plus outer edge of border if borderWidth > 0)
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - the name of the class as a String
text - get or set the text on the path
path - read-only access to path - but can manipulate the path
letters - access to ZIM Container of labels used for letters
for instance labels.loop(function (label) {label.color = red;});
or animate as a sequence labels.animate({props:{scale:1.5}, loop:true, rewind:true, sequence:200});
numLetters - how many letters - same as letters.numChildren
percents - access to the array of percents for letter positioning - resize() after changing unless interactive which auto resizes
color - get or set the color of the text
allowToggle - get or set the Boolean to allow toggling the path
interactive - get or set the Boolean to allow interaction with the path
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+54.5
zim.LabelOnPath = function(label, path, percentAngle, percents, showPath, allowToggle, interactive, onTop, style, group, inherit) {
var sig = "label, path, percentAngle, percents, showPath, allowToggle, interactive, onTop, style, group, inherit";
var duo; if (duo = zob(zim.LabelOnPath, arguments, sig, this)) return duo;
z_d("54.5");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "LabelOnPath";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(label)) label = DS.label!=null?DS.label:new zim.Label("Label on Path");
if (zot(path)) path = DS.path!=null?DS.path:new zim.Squiggle({points:[[0,0,0,0,-86,57,86,-57],[300,150,0,0,-133,21,133,-21]]});
if (zot(percentAngle)) percentAngle = DS.percentAngle!=null?DS.percentAngle:100;
if (zot(percents)) percents = DS.percents!=null?DS.percents:null;
if (zot(showPath)) showPath = DS.showPath!=null?DS.showPath:true;
if (zot(allowToggle)) allowToggle = DS.allowToggle!=null?DS.allowToggle:true;
if (zot(interactive)) interactive = DS.interactive!=null?DS.interactive:true;
if (zot(onTop)) onTop = DS.onTop!=null?DS.onTop:false;
path.addTo(this);
var that = this;
this.path = path;
this.allowToggle = allowToggle;
path.interactive = interactive;
if (typeof label == "string") label = new zim.Label(label);
var lastAlpha = path.alpha;
if (!showPath) path.alp(0);
path.onTop = onTop;
var letters = this.letters = new zim.Container().addTo(this);
if (!percents) {
percents = [];
for (var i=0; i=0; i--) {
letters.getChildAt(i).dispose();
}
that.numLetters = label.text.length;
for (var i=0; i180?(point.angle-360):point.angle)*percentAngle/100);
}
return this;
}
setText();
this.showPath = function(controls) {
this.toggle(true);
path.toggle(controls)
return this;
}
this.hidePath = function() {
this.toggle(false);
return this;
}
Object.defineProperty(that, 'text', {
get: function() {
return label.text;
},
set: function(value) {
label.text = value;
percents = [];
for (var i=0; i0 && zot(arcBorderColor)) arcBorderColor = "#000000";
else if (zot(arcBorderWidth) && !zot(arcBorderColor)) arcBorderWidth = 2;
arc.graphics.f(null).s(arcBorderColor).ss(arcBorderWidth).arc(0,0,radius, (startAngle-90)*Math.PI/180, (startAngle-90+totalAngle)*Math.PI/180)
}
Object.defineProperty(this, 'color', {
get: function() {
return color;
},
set: function(value) {
color = value;
for (var i=0; i0) letter.mov(spacings[i-1]?spacings[i-1]:0);
}
this.regX = this.getBounds().x;
this.regY = this.getBounds().y;
Object.defineProperty(this, 'color', {
get: function() {
return color;
},
set: function(value) {
color = value;
for (var i=0; i 0) {
b.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
}
// assumes center reg
b.x = width / 2;
b.y = height / 2;
}
}
that.addChild(that.backing);
if (borderWidth) {
that.border = new zim.Rectangle(width, height, "rgba(0,0,0,0)", borderColor, borderWidth, corner, dashed, null, false);
that.addChild(that.border);
}
function setPattern(type, pattern) {
that[type] = new zim.Container(width, height, null, null, false).centerReg(null, null, false);
if (shadowColor != -1 && shadowBlur > 0) {
var shadowRect = new zim.Rectangle(width-2, height-2, "#666", null, null, corner, null, null, false).center(that[type]);
shadowRect.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
}
var mask = that[type].mask = new zim.Rectangle(width, height, type.indexOf("roll")>=0?rollBackgroundColor:backgroundColor, null, null, corner, null, null, false).addTo(that[type]);
pattern.centerReg(mask);
pattern.setMask(mask.shape);
that[type].pattern = pattern;
return that[type];
}
//~~~~~~~~~~~~~ ICONS
that.icon = zot(icon)?(DS.icon!=null?DS.icon.clone():null):icon;
that.rollIcon = zot(rollIcon)?(DS.rollIcon!=null?DS.rollIcon.clone():null):rollIcon;
that.waitIcon = zot(waitIcon)?(DS.waitIcon!=null?DS.waitIcon.clone():null):waitIcon;
that.rollWaitIcon = zot(rollWaitIcon)?(DS.rollWaitIcon!=null?DS.rollWaitIcon.clone():null):rollWaitIcon;
that.toggleIcon = zot(toggleIcon)?(DS.toggleIcon!=null?DS.toggleIcon.clone():null):toggleIcon;
that.rollToggleIcon = zot(rollToggleIcon)?(DS.rollToggleIcon!=null?DS.rollToggleIcon.clone():null):rollToggleIcon;
var iconTypes = ["icon", "rollIcon", "toggleIcon", "rollToggleIcon", "waitIcon", "rollWaitIcon"];
for (var i=0; i 0) { // add an overlay
var gr = new createjs.Shape();
gr.graphics.lf(["rgba(255,255,255,"+gradient+")","rgba(0,0,0,"+gradient+")"], [0, 1], 0, 0, 0, height-borderWidth);
gr.graphics.rc(borderWidth/2, borderWidth/2, width-borderWidth, height-borderWidth, corner[0], corner[1], corner[2], corner[3]);
this.addChild(gr);
}
if (gloss > 0) { // add an overlay
var gl = new createjs.Shape();
gl.graphics.f("rgba(255,255,255,"+gloss+")");
gl.graphics.rc(borderWidth/2, borderWidth/2, width-borderWidth, (height-borderWidth)/2, corner[0], corner[1], 0, 0);
gl.graphics.f("rgba(0,0,0,"+gloss+")");
gl.graphics.rc(borderWidth/2, height/2, width-borderWidth, (height-borderWidth)/2, 0, 0, corner[2], corner[3]);
this.addChild(gl);
}
//~~~~~~~~~~~~~ HITAREA AND LABEL
var hitArea;
var rect;
if (hitPadding > 0) makeHitArea();
function makeHitArea() {
rect = new createjs.Shape();
rect.graphics.f("#000").r(-hitPadding,-hitPadding,width+hitPadding*2,height+hitPadding*2);
that.hitArea = hitArea = rect;
}
this.addChild(label);
label.center(this);
// label.y+=(typeof zimDefaultFrame!="undefined" && zimDefaultFrame.retina!=true)?1:0;
label.y+=1;
this.label = label;
zim.pos(label, (align=="left"||align=="right")?indentHorizontal:null, (valign=="top"||valign=="bottom")?indentVertical:null, align=="right", valign=="bottom");
//~~~~~~~~~~~~~ TOGGLE STATE
this.toggled = false;
if (toggleOkay) {
var originalText = label.text;
this.on(toggleEvent, function() {
that.toggled = !that.toggled;
setToggled();
});
}
function setToggled() {
if (that.toggled) {
if (!zot(toggle)) that.text = toggle;
// for toggle - may start in rollover or could be manually called
if (that.rolled) {
if (that.rollToggleBacking) changeObject("rollToggleBacking", that.rollToggleBacking);
else if (that.toggleBacking) changeObject("toggleBacking", that.toggleBacking);
if (that.rollToggleIcon) changeObject("rollToggleIcon", that.rollToggleIcon);
else if (that.toggleIcon) changeObject("toggleIcon", that.toggleIcon);
} else {
if (that.toggleBacking) changeObject("toggleBacking", that.toggleBacking);
if (that.toggleIcon) changeObject("toggleIcon", that.toggleIcon);
}
} else {
that.text = originalText;
setOriginalObjects();
}
if (that.stage) that.stage.update();
}
function setOriginalObjects() {
if (that.rolled) {
if (zot(backing) && !that.rollBacking) that.backing.color = rollBackgroundColor;
if (that.rollBacking) changeObject("rollBacking", that.rollBacking);
else if (that.backing) changeObject("backing", that.backing);
if (that.rollIcon) changeObject("rollIcon", that.rollIcon);
else if (that.icon) changeObject("icon", that.icon);
else changeObject("icon", null);
} else {
if (zot(backing)) that.backing.color = backgroundColor;
if (that.backing) changeObject("backing", that.backing);
if (that.icon) changeObject("icon", that.icon);
else changeObject("icon", null);
}
}
this.toggle = function(state) {
if (!toggleOkay) {
if (zon) zogy("Button() - can't toggle with wait parameters provided");
return that;
}
if (zot(state)) {
that.toggled = !that.toggled;
} else {
that.toggled = state;
}
setToggled();
return that;
}
//~~~~~~~~~~~~~ WAIT STATE
var pressCheck = false;
that.waiting = false;
var willBeWaiting = false;
var waitTimeout;
var waitStartText;
// var waitStartBackgroundColor;
var waitStartTextBackgroundColor = that.label.color;
var waitStartRollTextBackgroundColor = that.label.rollColor;
var waitStartEnabled;
var waitModalEvent;
var waitEvent = this.on("mousedown", function() {
pressCheck=true;
doWait();
});
function doWait() {
if ((!zot(wait) || !zot(waitBacking) || !zot(rollWaitBacking)) && !that.waiting) {
willBeWaiting = true;
if (zot(waitEnabled)) waitEnabled = true;
if (waitModal) waitModalEvent = that.stage.on("stagemousedown", function(e) {
if (!that.hitTestPoint(e.stageX/zim.scaX, e.stageY/zim.scaY)) that.clearWait();
}, null, true); // run only once
// wait before setting the waiting property so first click is not a waiting
setTimeout(function(){that.waiting = true;}, 50);
// set button to waiting state
waitStartText = label.text;
if (!zot(waitColor)) that.label.color = waitColor;
if (!zot(rollWaitColor)) that.label.rollColor = rollWaitColor;
waitStartEnabled = that.enabled;
if (!waitEnabled && that.enabled) that.enabled = false;
if (!zot(wait)) that.text = wait;
if (that.rolled) {
if (zot(backing) && !that.rollWaitBacking) that.backing.color = rollWaitBackgroundColor;
if (that.rollWaitBacking) changeObject("rollWaitBacking", that.rollWaitBacking);
else if (that.waitBacking) changeObject("waitBacking", that.waitBacking);
if (that.rollWaitIcon) changeObject("rollWaitIcon", that.rollWaitIcon);
else if (that.waitIcon) changeObject("waitIcon", that.waitIcon);
} else {
if (zot(backing) && !that.waitBacking) that.backing.color = waitBackgroundColor;
if (that.waitBacking) changeObject("waitBacking", that.waitBacking);
if (that.waitIcon) changeObject("waitIcon", that.waitIcon);
}
if (zot(waitTime)) waitTime = 30000; // 30 seconds
if (waitTimeout) waitTimeout.clear();
waitTimeout = zim.timeout(waitTime, function() {
// set button to proper text, icon, backing, colors, etc.
if (!that.enabled) that.enabled = waitStartEnabled;
that.clearWait();
that.dispatchEvent("waited");
});
if (that.stage) that.stage.update();
}
};
this.wait = function() {
doWait();
}
this.clearWait = function() {
if (!waitTimeout) return that;
if (waitModalEvent) that.stage.off("stagemousedown", waitModalEvent);
waitTimeout.clear();
that.text = waitStartText;
setOriginalObjects();
that.label.color = waitStartTextBackgroundColor;
that.label.rollColor = waitStartRollTextBackgroundColor;
setTimeout(function(){that.waiting = false;}, 55); // give time for first click to see not waiting yet
willBeWaiting = false;
if (that.stage) that.stage.update();
return that;
}
this.removeWait = function() {
that.clearWait();
wait = null;
that.waitBacking = null;
that.rollWaitBacking = null;
that.off("mousedown", waitEvent);
return that;
}
//~~~~~~~~~~~~~ INTERACTION
this.on("pressup", function(){
pressCheck=false;
if (that.rollPersist && !reallyOn) removeRoll();
});
// visually swap button backing or icon
// on clicks if wait or toggle and on mouseover and mouseout
// note - icon will be removed if newObject is null
// BUT - backing will be ignored if newObject is null
// so these act slightly differently!
function changeObject(type, newObject) {
if (type.indexOf("con")>=0) { // icon
for (var i=0; i=0?that.numChildren-1:0);
if (that.stage) that.stage.update();
}
if (newObject) {
if (zot(backing) && type == "backing") backing = newObject;
if (newObject.type == "Pattern") newObject = setPattern(type, newObject);
that[type] = newObject;
that[type].x = width/2;
that[type].y = height/2;
} else {
that[type] = null;
}
return that;
}
if (style!==false) if (style!==false) zimStyleTransforms(this, DS);
this.clone = function(exact) {
var but = new zim.Button(
width, height, label.clone(),
(exact||!zim.isPick(oa[0]))?backgroundColor :oa[0],
(exact||!zim.isPick(oa[0]))?rollBackgroundColor :oa[1],
(exact||!zim.isPick(oa[0]))?color :oa[2],
(exact||!zim.isPick(oa[0]))?rollColor :oa[3],
originalBorderColor, borderRollColor, originalBorderWidth, corner, shadowColor, shadowBlur, hitPadding, gradient, gloss, dashed,
!zot(backing)?that.backing.clone():null,
!zot(rollBacking)?that.rollBacking.clone():null,
rollPersist,
!zot(icon)?icon.clone():null, !zot(rollIcon)?rollIcon.clone():null,
toggle,
!zot(toggleBacking)?toggleBacking.clone():null,
!zot(rollToggleBacking)?rollToggleBacking.clone():null,
!zot(toggleIcon)?toggleIcon.clone():null,
!zot(rollToggleIcon)?rollToggleIcon.clone():null,
toggleEvent,
wait, waitTime, waitBackgroundColor, rollWaitBackgroundColor, waitColor, rollWaitColor, waitModal, waitEnabled,
!zot(waitBacking)?waitBacking.clone():null,
!zot(rollWaitBacking)?rollWaitBacking.clone():null,
!zot(waitIcon)?waitIcon.clone():null,
!zot(rollWaitIcon)?rollWaitIcon.clone():null,
align, valign, indent, indentHorizontal, indentVertical,
style,
this.group
);
return that.cloneProps(but);
}
}
zim.extend(zim.Button, zim.Container, "clone", "zimContainer", false);
//-55
/*--
zim.CheckBox = function(size, label, startChecked, color, backgroundColor, borderColor, borderWidth, corner, margin, indicatorType, indicatorColor, tap, style, group, inherit)
CheckBox
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
A checkbox that when pressed toggles the check and a checked property.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var checkBox = new CheckBox(50, "TEST");
checkBox.center(stage);
checkBox.on("change", function() {
zog(checkBox.checked); // will be true then false, etc.
});
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
size - (default 60) size in pixels (always square)
label - (default null) ZIM Label object - or String to make a default label (black)
startChecked - (default false) an initial parameter to set checked if true
color - (default "#111") the text color of the label
backgroundColor - (default "rgba(255,255,255,.8)") the background color of the box
borderColor - (default "#111") the color of the border
borderWidth - (default size/10) thickness of the border
corner - (default 0) the round of the corner
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
margin - (default 10) is on outside of box so clicking or pressing is easier
indicatorType - (default check) could be square (box) or x
indicatorColor - (default borderColor or black if no border) the color of the indicator
tap - (default false) set to true to tap to activate CheckBox rather than mousedown or click
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
setChecked(Boolean) - defaults to true to set button checked (or use checked property)
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
checked - gets or sets the check of the box
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
label - gives access to the label
text - the text of the label
background - the Rectangle of the checkBox
indicator - gives access to the check mark ie. indicator.sca(.8);
indicatorColor - get or set the color of the indicator
enabled - default is true - set to false to disable
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
OPTIMIZED
This component is affected by the general OPTIMIZE setting (default is false)
if set to true, you will have to stage.update() after setting certain properties
ACTIONEVENT
This component is affected by the general ACTIONEVENT setting
The default is "mousedown" - if set to something else the component will act on click (press)
EVENTS
dispatches a "change" event when pressed on but not when the checked property is set
ALSO: See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+56
zim.CheckBox = function(size, label, startChecked, color, backgroundColor, borderColor, borderWidth, corner, margin, indicatorType, indicatorColor, tap, style, group, inherit) {
var sig = "size, label, startChecked, color, backgroundColor, borderColor, borderWidth, corner, margin, indicatorType, indicatorColor, tap, style, group, inherit";
var duo; if (duo = zob(zim.CheckBox, arguments, sig, this)) return duo;
z_d("56");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "CheckBox";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(size)) size = DS.size!=null?DS.size:60;
if (zot(label)) label = DS.label!=null?DS.label:null;
if (zot(startChecked)) startChecked = DS.startChecked!=null?DS.startChecked:false;
var myChecked = startChecked;
if (zot(color)) color = DS.color!=null?DS.color:"#111";
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"rgba(255,255,255,.8)";
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:"#111";
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:size/10;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = size/10;
if (zot(corner)) corner=DS.corner!=null?DS.corner:0;
if (typeof label === "string" || typeof label === "number") label = new zim.Label({
text:label, size:size*5/6, color:color, valign:"center",
backing:"ignore", shadowColor:"ignore", shadowBlur:"ignore", padding:"ignore", backgroundColor:"ignore",
group:this.group
});
if (zot(margin)) margin = DS.margin!=null?DS.margin:size/5;
if (indicatorType != "box" && indicatorType != "square" && indicatorType != "x") indicatorType = DS.indicatorType!=null?DS.indicatorType:"check";
if (zot(indicatorColor)) indicatorColor = DS.indicatorColor!=null?DS.indicatorColor:borderWidth>0?borderColor:"black";
this.setBounds(-margin, -margin, size+margin*2, size+margin*2);
if (zot(tap)) tap = DS.tap!=null?DS.tap:false;
var that = this;
this.cursor = "pointer";
var box = new zim.Rectangle(size, size, backgroundColor, null, null, corner);
var box2 = new zim.Rectangle(size*5/7, size*5/7,"rgba(0,0,0,0)", borderColor, borderWidth, corner);
box2.x = size/7; box2.y = size/7;
this.addChild(box, box2);
var fullWidth = size;
if (label) {
label.center(that);
label.x = that.getBounds().width;
this.label = label;
this.setBounds(-margin, -margin, size+margin*3+label.getBounds().width, Math.max(size+margin*2, label.getBounds().height));
fullWidth = label.x + label.width;
}
var backing = new zim.Shape({style:false});
g = backing.graphics;
g.f("rgba(0,0,0,.01)").r(
this.getBounds().x,
this.getBounds().y,
fullWidth+(margin*2),
this.getBounds().height
);
this.hitArea = backing;
// hitArea will stop rollovers on labels but oh well
var check = new zim.Shape({style:false});
var g2 = check.graphics;
if (indicatorType == "check") {
g2.f(indicatorColor).p("AnQAdICBiaIEEDZIF8nfICfB4In/KPg"); // width about 90 reg in middle
} else if (indicatorType == "box" || indicatorType == "square") {
g2.f(indicatorColor).dr(-35,-35,70,70);
} else { // x
g2.f(indicatorColor).p("AmJEVIEUkTIkXkWIB4h5IEWEYIETkTIB4B3IkTESIEQERIh4B4IkRkRIkSEVg"); // width about 90 reg in middle
}
var cW = 95
check.setBounds(-cW/2, -cW/2, cW, cW);
var scale = size/(cW+66);
check.scaleX = check.scaleY = scale;
check.alpha = .9;
check.x = size/2;
check.y = size/2;
if (myChecked) this.addChild(check);
if (tap) {
this.tap(toggleCheck);
} else {
this.on((!zns?ACTIONEVENT=="mousedown":zim.ACTIONEVENT=="mousedown")?"mousedown":"click", toggleCheck);
}
Object.defineProperty(that, 'checked', {
get: function() {
return myChecked;
},
set: function(value) {
that.setChecked(value);
}
});
this.toggle = function(type) {
if (zot(type)) type = !myChecked;
that.setChecked(type);
}
Object.defineProperty(that, 'toggled', {
get: function() {
return myChecked;
},
set: function(value) {
that.setChecked(value);
}
});
Object.defineProperty(that, 'text', {
get: function() {
if (label) return label.text;
},
set: function(value) {
if (label) {
label.text = value;
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
};
}
});
Object.defineProperty(check, 'indicatorColor', {
get: function() {
return indicatorColor;
},
set: function(value) {
if (myChecked) {that.removeChild(check);}
check = new createjs.Shape();
g2 = check.graphics;
indicatorColor = value;
g2.f(indicatorColor).p("AnQAdICBiaIEEDZIF8nfICfB4In/KPg");
check.scaleX = check.scaleY = scale;
check.alpha = .9;
check.x = size/2;
check.y = size/2;
if (myChecked) that.addChild(check);
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
Object.defineProperty(that, 'indicator', {
get: function() {
return check;
},
set: function(value) {
zog("ZIM CheckBox - check is read only");
}
});
this._enabled = true;
Object.defineProperty(that, 'enabled', {
get: function() {
return that._enabled;
},
set: function(value) {
zenable(that, value);
}
});
function toggleCheck(e) {
myChecked = !myChecked;
that.setChecked(myChecked);
that.dispatchEvent("change");
}
this.setChecked = function(value) {
if (zot(value)) value = true;
myChecked = value;
if (myChecked) {
that.addChild(check);
} else {
that.removeChild(check);
}
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
return that;
}
if (style!==false) zimStyleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.CheckBox(size, label?label.clone():"", startChecked, color, backgroundColor, borderColor, borderWidth, corner, margin, indicatorType, indicatorColor, tap, style, this.group, inherit));
}
}
zim.extend(zim.CheckBox, zim.Container, "clone", "zimContainer", false);
//-56
/*--
zim.RadioButtons = function(size, buttons, vertical, color, backgroundColor, spacing, margin, always, indicatorColor, style, group, inherit)
RadioButtons
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
A radio button set that lets you pick from choices.
Radio buttons can display radio buttons vertically (default) or horizontally.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var radioButtons = new RadioButtons(50, ["ONE", "TWO", "THREE"]);
radioButtons.center(stage);
radioButtons.on("change", function() {
zog(radioButtons.text); // will be ONE, TWO or THREE
zog(radioButtons.selectedIndex); // will be 0, 1, or 2
});
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
size - (default 60) in pixels
buttons - an array of button data objects as follows:
[{label:ZIM Label or text, id:optional id, selected:optional Boolean}, {etc...}]
or just a list of labels for default labels ["hi", "bye", "what!"]
vertical - (default true) displays radio buttons vertically - set to false to display horizontally
color - (default "#111") the text color of the label
backgroundColor - (default "rgba(255,255,255,.8)") the background color of the circle
borderColor - (default "#111") the color of the border
borderWidth - (default size/9) thickness of the border
spacing - (size*.2 for vertical and size for horizontal) the space between radio button objects
margin - (size/5) the space around the radio button itself
always - (default false) if set true, cannot click on selection to unselect it
indicatorColor - (default borderColor or black) the color of the indicator
selectedIndex - (default 0) - set the selectedIndex at start
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
setSelected(num) - sets the selected index (or use selectedIndex) -1 is default (none)
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
selected - gets the selected object - selected.label, selected.id, etc.
selectedIndex - gets or sets the selected index of the buttons
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
label - current selected label object
text - current selected label text
id - current selected id
buttons - an array of button Container objects holding the shape and label (note - different than buttons parameter)
labels - an array of the ZIM Label objects. labels[0].text = "YUM"; labels[2].y -= 10;
indicators - an array of the zim Shape dot objects. indicators[0].color = "yellow";
enabled - default is true - set to false to disable
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
OPTIMIZED
This component is affected by the general OPTIMIZE setting (default is false)
if set to true, you will have to stage.update() after setting certain properties
and stage.update() in change event to see component change its graphics
ACTIONEVENT
This component is affected by the general ACTIONEVENT setting
The default is "mousedown" - if set to something else the component will act on click (press)
EVENTS
dispatches a "change" event when pressed but not when selectedIndex is set
then ask for the properties above for info
ALSO: See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+57
zim.RadioButtons = function(size, buttons, vertical, color, backgroundColor, borderColor, borderWidth, spacing, margin, always, indicatorColor, selectedIndex, style, group, inherit) {
var sig = "size, buttons, vertical, color, backgroundColor, borderColor, borderWidth, spacing, margin, always, indicatorColor, selectedIndex, style, group, inherit";
var duo; if (duo = zob(zim.RadioButtons, arguments, sig, this)) return duo;
z_d("57");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "RadioButtons";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(size)) size = DS.size!=null?DS.size:60;
size = Math.max(5, size);
if (zot(buttons)) buttons = DS.buttons!=null?DS.buttons:["A", "B", "C"];
if (zot(vertical)) vertical = DS.vertical!=null?DS.vertical:true;
if (zot(color)) color = DS.color!=null?DS.color:"#111";
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"rgba(255,255,255,.8)";
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:"#111";
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:size/9;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = size/10;
if (zot(spacing)) spacing = (vertical) ? DS.spacing!=null?DS.spacing:size*.2 : DS.spacing!=null?DS.spacing:size;
if (zot(margin)) margin = DS.margin!=null?DS.margin:size/5;
if (zot(indicatorColor)) indicatorColor = DS.indicatorColor!=null?DS.indicatorColor:borderWidth>0?borderColor:"black";;
var that = this;
this.cursor = "pointer";
this.labels = [];
this.indicators = [];
var currentObject; // reference to the current data object
if (typeof buttons == "string") {
// convert to buttons object literal (for cloning)
var bString = buttons;
buttons = [];
for (var i=0; i=0; i--) {
data = buttons[i];
if (data.selected && data.selected === true) {
if (!selectedCheck) {
selectedCheck = true; // first item marked selected
that.id = data.id;
} else {
data.selected = "false"; // turn off selected
}
}
}
buttonContainer.removeAllChildren();
that.buttons = [];
var but; var currentLocation = 0;
for (var i=0; i= 0) {
but = buttonContainer.getChildAt(value);
var lastIndex = -2;
if (currentObject) lastIndex = currentObject.index;
currentObject = but.obj;
}
if (value == -1 || lastIndex == currentObject.index) {
currentObject = null;
that.id = null;
that.label = null;
that.text = "";
} else {
but.addChild(but.check);
that.id = currentObject.id;
that.label = currentObject.label;
if (that.label) that.text = that.label.text;
}
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
return that;
}
// getter setter methods
Object.defineProperty(that, 'selected', {
get: function() {
return currentObject;
},
set: function(value) {
zog("ZIM RadioButton - selected is read only");
}
});
Object.defineProperty(that, 'selectedIndex', {
get: function() {
return (currentObject) ? currentObject.index : -1;
},
set: function(value) {
var index = value;
if (always) {if (that.selectedIndex == index) return;}
that.setSelected(index);
}
});
this._enabled = true;
Object.defineProperty(that, 'enabled', {
get: function() {
return that._enabled;
},
set: function(value) {
zenable(that, value);
}
});
if (zot(selectedIndex)) selectedIndex=DS.selectedIndex!=null?DS.selectedIndex:0;
that.selectedIndex = selectedIndex;
zimStyleTransforms(this, DS)
this.clone = function() {
var buttonsCopy = zim.copy(buttons);
for (var i=0; i 0) {
this.background.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
}
if (label) {
this.addChild(label);
label.x = width + 2 + margin + borderWidth;
label.y = height/2;
this.label = label;
this.setBounds(-margin, -margin, width+margin*3+borderWidth+label.getBounds().width, Math.max(height+margin*2, label.getBounds().height));
}
if (labelLeft) {
this.addChild(labelLeft);
labelLeft.x = 0;
that.background.x += labelLeft.width + 3 + margin + borderWidth;
that.label.x += labelLeft.width + 3 + margin + borderWidth;
labelLeft.y = height/2;
this.labelLeft = labelLeft;
this.setBounds(-margin, -margin, that.getBounds().width+labelLeft.width + 3 + margin + borderWidth, that.getBounds().height);
}
this.expand(zim.mobile()?20:10);
this.tap(function (e) {
if (labelLeft) {
var point = that.localToGlobal(labelLeft.width+3+margin+borderWidth+width/2, 0);
if ((e.stageX/zim.scaX < (point.x-width/2) && !that.toggled) || (e.stageX/zim.scaX >= (point.x+width/2) && that.toggled)) return;
}
that.toggled = !that.toggled;
setToggle();
that.dispatchEvent("change");
}, zim.mobile()?20:10);
var swipe = new zim.Swipe(this, 20, 200);
swipe.on("swipe", function (e) {
if (e.swipeX==0) {
return;
} else if (e.swipeX==1 && that.toggled) {
return;
} else if (e.swipeX==-1 && !that.toggled) {
return;
}
that.toggled = !that.toggled;
setToggle();
that.dispatchEvent("change");
});
function setToggle(immediate){
var oldX = that.indicator.x;
var t = time;
if (immediate===true) t = 0;
if (indicatorType=="rectangle" || indicatorType=="square") {
that.indicator.pos(height*.2, null, that.toggled);
if (time>0) that.indicator.animate({props:{x:oldX}, from:true, time:t});
} else {
that.indicator.pos(height*.175, null, that.toggled);
if (time>0) that.indicator.animate({props:{x:oldX}, from:true, time:t});
}
that.background.color = that.toggled?toggleBackgroundColor:backgroundColor;
that.text = that.toggled?(that.label?that.label.text:"on"):(that.labelLeft?that.labelLeft.text:"off");
if (that.zimAccessibility) {
var string = "Toggle set to " + (that.toggled?(that.label?that.label.text+".":"on."):(that.labelLeft?that.labelLeft.text+".":"off."));
setTimeout(function() {that.zimAccessibility.talk(string);}, 50);
}
}
Object.defineProperty(that, 'textLeft', {
get: function() {
if (labelLeft) return labelLeft.text;
},
set: function(value) {
if (labelLeft) {
labelLeft.text = value;
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
};
}
});
that.toggle = function(state, immediate) {
var lastToggle = that.toggled;
if (zot(state)) state = true;
that.toggled = state;
if (lastToggle != that.toggled) setToggle(immediate);
return that;
}
that.text = that.toggled?(that.label?that.label.text:"on"):(that.labelLeft?that.labelLeft.text:"off");
this._enabled = true;
Object.defineProperty(that, 'enabled', {
get: function() {
return that._enabled;
},
set: function(value) {
zenable(that, value);
}
});
if (style!==false) zimStyleTransforms(this, DS);;
this.clone = function() {
return that.cloneProps(new zim.Toggle(width, height, label?label.clone():"", startToggled, backgroundColor, margin, indicatorType, indicatorColor, tap, toggleBackgroundColor, color, borderColor, borderWidth, corner, indicatorCorner, shadowColor, shadowBlur, time, labelLeft?labelLeft.clone():"", style, this.group, inherit));
}
}
zim.extend(zim.Toggle, zim.Container, "clone", "zimContainer", false);
//-57.5
/*--
zim.Tip = function(text, align, valign, margin, marginH, marginV, outside, target, size, font, color, rollColor, shadowColor, shadowBlur, textAlign, textValign, lineWidth, lineHeight, fontOptions, backing, outlineColor, outlineWidth, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backgroundDashed, padding, paddingHorizontal, paddingVertical, shiftHorizontal, shiftVertical, rollPersist, labelWidth, labelHeight, maxSize, style, group, inherit)
Tip
zim class - extends a a zim.Label which extends a zim.Container which extends a createjs.Container
DESCRIPTION
A Tip() can be used to show some extra information - the tip disappears after an amount of time
Tip has easy positioning along the inside edges or the outside edges of a target.
NOTE: Tip places the tip on the stage when the show() method is called
You can reposition with .mov() etc. if desired
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
new Tip("Press Circle").show(1000); // wait one second and show tip at 40 pixels from bottom right
var circle = new Circle().center().tap(function () {
circleTip.show();
});
var circleTip = new Tip({
text:"This is a default ZIM Circle",
backgroundColor:white,
color:black,
outside:true, // outside the circle
target:circle,
align:"center",
valign:"bottom",
margin:14,
corner:0,
size:20
});
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
text - (default "Here's a tip!") String for the the text of the tip
align - (default "right") the horizontal position of the tip ("left", "center"/"middle", "right")
valign - (default "bottom") the vertical position of the tip ("top", "center"/"middle", "bottom")
margin - (default 40) distance from side (unless centered) in pixels
marginH - (default margin) distance from horizontal edges
marginV - (default margin) distance from vertical edges
outside - (default false) set to true to place Tip on outside of container
target - (default ZimDefaultFrame's stage) tip is placed on stage relative to container
** the rest are parameters for a Label (align and valign are set as textAlign and textValign)
size - (default 36) the size of the font in pixels
font - (default arial) the font or list of fonts for the text
color - (default "black") color of font (any CSS color)
rollColor - (default color) the rollover color of the font
shadowColor - (default "rgba(0,0,0,.3)") for no shadow - set to any css color to see
shadowBlur - (default 1) if shadow is present
textAlign - ((default "left") text registration point alignment also "center" and "right"
textValign - (default "center") vertical registration point alignment alse "middle / center", "bottom"
lineWidth - (default false) for no wrapping (use \n) Can set to number for wrap
lineHeight - (default getMeasuredLineHeight) set to number to adjust line height
fontOptions - (default null) css VALUES as a single string for font-style font-variant font-weight
eg. "italic bold small-caps" or just "italic", etc.
backing - (default null) a Display object for the backing of the label (eg. Shape, Bitmap, Container, Sprite)
see ZIM Pizzazz module for a fun set of Shapes like Boomerangs, Ovals, Lightning Bolts, etc.
outlineColor - (default null - or black if outlineWidth set) - the color of the outline of the text
outlineWidth - (default null - or (size*.2) if outlineColor set) - the thickness of the outline of the text
backgroundColor - (default null) set to CSS color to add a rectangular color around the label
The background color will change size to match the text of the label
Note: the backgroundColor is different than a backing which can be any Display Object
and background parameters are ignored if a backing parameter is set
backgroundBorderColor - (default null) the background stroke color
backgroundBorderWidth - (default null) thickness of the background border
corner - (default 0) the round of corner of the background if there is one
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
backgroundDashed - (default null) set to true for dashed background border (if backgroundBorderColor or backgroundBorderWidth set)
padding - (default 10 if backgroundColor set) places the border this amount from text (see paddingHorizontal and paddingVertical)
padding parameters are ignored if there is no backgroundColor set (also ignored if a backing parameter is set)
paddingHorizontal - (default padding) places border out at top bottom
paddingVertical - (default padding) places border out at left and right
shiftHorizontal - (default 0) move the label (CreateJS Text) inside the Label container horizontally
shiftVertical - (default 0) move the label (CreateJS Text) inside the Label container vertically
rollPersist - (default false) set to true to maintain rollover stage as long as mousedown or press is activated (used by Buttons)
labelWidth - (default null) the same as the lineWidth - the text will wrap at the labelWidth (added to match labelHeight)
labelHeight - (default null) the height of the text - setting this will probably alter the font size - so the size parameter is overwritten
for labelHeight to work, the labelWidth must also be set
using labelWidth and labelHeight together allow you to fit as much text into specified width and height dimensions
maxSize - (default null) set to limit the font size when using labelWidth and labelHeight
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
show(delay, time) - show the tip - delay in ms defaults to 0 and time in ms defaults to 2000
hide() - hides tip - show() will also hide the tip automatically after the time provided
clear() - hides tip and removes the call to a delayed tip using a delay time in show()
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: See all methods of a Label() such as setColorRange(), etc.
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
align - get or set the horizontal alignment
valign - get or set the vertical alignment
text - get or set the text of the Tip
ALSO: See all properties of a Label() such as size, color, etc.
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+57.6
zim.Tip = function(text, align, valign, margin, marginH, marginV, outside, target, size, font, color, rollColor, shadowColor, shadowBlur, textAlign, textValign, lineWidth, lineHeight, fontOptions, backing, outlineColor, outlineWidth, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backgroundDashed, padding, paddingHorizontal, paddingVertical, shiftHorizontal, shiftVertical, rollPersist, labelWidth, labelHeight, maxSize, style, group, inherit) {
var sig = "text, align, valign, margin, marginH, marginV, outside, target, size, font, color, rollColor, shadowColor, shadowBlur, textAlign, textValign, lineWidth, lineHeight, fontOptions, backing, outlineColor, outlineWidth, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backgroundDashed, padding, paddingHorizontal, paddingVertical, shiftHorizontal, shiftVertical, rollPersist, labelWidth, labelHeight, maxSize, style, group, inherit";
var duo; if (duo = zob(zim.Tip, arguments, sig, this)) return duo;
z_d("57.6");
this.group = group;
var DS = style===false?{}:zim.getStyle("Tip", this.group, inherit);
if (zot(text)) text = DS.text!=null?DS.text:"Here's a tip!";
if (zot(margin)) margin = DS.margin!=null?DS.margin:40;
if (zot(marginH)) marginH = DS.marginH!=null?DS.marginH:margin;
if (zot(marginV)) marginV = DS.marginV!=null?DS.marginV:margin;
if (zot(align)) align = DS.align!=null?DS.align:"right";
if (zot(valign)) valign = DS.valign!=null?DS.valign:"bottom";
if (zot(outside)) outside = DS.outside!=null?DS.outside:false;
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:blue;
if (zot(color)) color = DS.color!=null?DS.color:white;
if (zot(corner)) corner = DS.corner!=null?DS.corner:25;
if (zot(corner)) corner = DS.corner!=null?DS.corner:25;
if (zot(corner)) corner = DS.corner!=null?DS.corner:25;
if (zot(paddingHorizontal)) paddingHorizontal = DS.paddingHorizontal!=null?DS.paddingHorizontal:14+(Array.isArray(corner)?corner[0]:corner);
if (zot(shadowColor) || shadowColor=="ignore") shadowColor=(DS.shadowColor!=null&&shadowColor!="ignore")?DS.shadowColor:"rgba(0,0,0,.3)";
if (zot(shadowBlur) || shadowBlur=="ignore") shadowBlur=(DS.shadowBlur!=null&&shadowBlur!="ignore")?DS.shadowBlur:1;
this.zimLabel_constructor(text, size, font, color, rollColor, null, null, textAlign, textValign, lineWidth, lineHeight, fontOptions, backing, outlineColor, outlineWidth, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backgroundDashed, padding, paddingHorizontal, paddingVertical, shiftHorizontal, shiftVertical, rollPersist, labelWidth, labelHeight, maxSize, style, group, zim.copy(DS));
this.type = "Tip";
if (outside) {
marginH = -marginH;
marginV = -marginV;
}
var that = this;
that.align = align;
that.valign = valign;
this.background.sha(shadowColor, 3, 5, shadowBlur);
this.show = function(delay, time) {
if (zot(delay)) delay = DS.delay!=null?DS.delay:0;
if (zot(time)) time = DS.time!=null?DS.time:2000;
var mess = "zim Tip(): Please pass in a reference to a container with bounds set as parameter to Tip";
if (zot(target)) {
if (zimDefaultFrame) {
target = zimDefaultFrame.stage;
} else {
return that;
}
} else if (!target.getBounds) {
return that;
} else if (zot(target.stage)) {
zog("zim display - Waiter(): The container must have a stage property");
return that;
}
if (delay > 0) {
that.showID = zim.timeout(delay, doShow);
} else {
doShow();
}
function doShow() {
if (target.boundsToGlobal) var b = target.boundsToGlobal();
else var b = target.getBounds();
var container = new zim.Container(b.x, b.y, b.width, b.height);
container.zimTemp = true;
container.loc(0, 0, target.stage);
if (that.align=="center" || that.align=="middle" || that.valign=="center" || that.valign=="middle") {
that.center(container);
}
that.pos((that.align=="center" || that.align=="middle")?null:marginH, (that.valign=="center" || that.valign=="middle")?null:marginV, (that.align=="right"), (that.valign=="bottom"), container);
if (outside) {
if (that.align=="right") that.x += that.width;
else if (that.align=="left") that.x -= that.width;
if (that.valign=="bottom") that.y += that.height;
else if (that.valign=="top") that.y -= that.height;
}
that.addTo(container.stage); // will transfer over position...
if (container.zimTemp && container.removeFrom) {container.removeFrom(); container = null;}
container = that.stage;
if (that.timeoutID) that.timeoutID.clear();
that.timeoutID = zim.timeout(time, function () {
that.hide();
container.stage.update();
});
// setTimeout(function() {
if (that.upID) container.stage.off("stagemouseup", that.upID);
that.upID = container.stage.on("stagemouseup", function () {
that.hide();
if (container.stage) container.stage.update();
});
// }, 200);
if (container.stage) container.stage.update();
}
return that;
}
this.hide = function() {
this.removeFrom();
if (this.timeoutID) this.timeoutID.clear();
if (this.upID && target.stage) target.stage.off("stagemouseup", this.downID);
return that;
}
this.clear = function() {
if (that.showID) that.showID.clear();
that.hide();
}
if (style!==false) zimStyleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.Tip(text, align, valign, margin, marginH, marginV, outside, target, size, font, color, rollColor, shadowColor, shadowBlur, textAlign, textValign, lineWidth, lineHeight, fontOptions, backing, outlineColor, outlineWidth, backgroundColor, backgroundBorderColor, backgroundBorderWidth, corner, backgroundDashed, padding, paddingHorizontal, paddingVertical, shiftHorizontal, shiftVertical, rollPersist, labelWidth, labelHeight, maxSize, style, this.group, inherit));
}
}
zim.extend(zim.Tip, zim.Label, "clone", "zimLabel", false);
//-57.6
/*--
zim.Panel = function(width, height, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, backgroundColor, borderColor, borderWidth, corner, arrow, align, shadowColor, shadowBlur, draggable, boundary, extraButton, style, group, inherit)
Panel
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
A simple panel with titleBar and optional arrow for more panels.
Panel can be set draggable but does not have a close button - try a Pane() or Window() for that
See: https://zimjs.com/explore/panel.html
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var panel = new Panel({titleBar:series("TODAY", "TOMORROW")})
.center();
// make a couple pages for the panels
// content for panel 1
var today = new Container(panel.width, panel.height).addTo(panel);
var sun = new Circle(30, yellow).center(today);
// content for panel 2
var tomorrow = new Container(panel.width, panel.height); // do not add yet
var label = new Label("-30").center(tomorrow);
// event to change content as panels change
panel.on("change", function () {
if (today.parent) {
today.removeFrom();
tomorrow.center(panel);
} else {
tomorrow.removeFrom();
today.center(panel);
}
});
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports VEE - parameters marked with ZIM VEE mean a zim Pick() object or Pick Literal can be passed
Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - (default 250) the width of the panel
height - (default 300) the height of the panel
titleBar - |ZIM VEE| (default "PANEL") a String or ZIM Label title for the panel that will be presented on a titleBar across the top
titleBarColor - |ZIM VEE| (default "black") the text color of the titleBar if a titleBar is requested
titleBarBackgroundColor - |ZIM VEE| (default "rgba(0,0,0,.2)") the background color of the titleBar if a titleBar is requested
titleBarHeight - (default fit label) the height of the titleBar if a titleBar is requested
backgroundColor - |ZIM VEE| (default #eee) background color (use clear - or "rbga(0,0,0,0)" for no background)
borderColor - |ZIM VEE| (default #888) border color
borderWidth - (default 1) the thickness of the border
corner - (default 0) the round of corner
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
arrow - (default true if more than one panel) set to false to not show an arrow if multiple panels
align - (default "left") set to "center", "middle" or "right" to align the label on the titleBar
shadowColor - (default "rgba(0,0,0,.3)" if shadowBlur) the shadow color - set to -1 for no shadow
shadowBlur - (default 14 if shadowColor) the shadow blur - set to -1 for no shadow
draggable - (default true if titleBar) set to false to not allow dragging titleBar to drag window
boundary - (default null) set to ZIM Boundary() object - or CreateJS.rectangle()
extraButton - (default null) creates a little square button with the letter R for reset
this is made with the group style id of "extraButton"
use the extraButton property to access the button to change its label or capture an event, etc.
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
nextPanel(index, event) - show next panel - the panels are set up to be a series or random or function based
this means there is not necessarily an order to be able to go backwards to... so, only forward!
If a series is provided to the Panel title, etc. then the index can be used to go to the title in the series at the index
event (default false) will dispatch a change event if nextPanel is called
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
titleBar - access to the titleBar container
label - access to the label of the current panel
text - access to the text of the current panel
titleBar - gives access to the titleBar Container - which also has a background property
titleBarLabel - gives access to the titleBar label
arrow - access to the next arrow
background - access to the background Rectangle
extraButton - access to the Label for the extra button if extraButton parameter is set to true
use this to set the text in the button (a one letter button is expected - for instance, i for info, x for close, etc.)
overlay - access to the overlay Rectangle used if enabled = false
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
enabled - default is true - set to false to disable
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
dispatches a "change" event when arrow is pressed to go to the next panel
ALSO: See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+57.7
zim.Panel = function(width, height, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, backgroundColor, borderColor, borderWidth, corner, arrow, align, shadowColor, shadowBlur, draggable, boundary, extraButton, style, group, inherit) {
var sig = "width, height, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, backgroundColor, borderColor, borderWidth, corner, arrow, align, shadowColor, shadowBlur, draggable, boundary, extraButton, style, group, inherit";
var duo; if (duo = zob(zim.Panel, arguments, sig, this)) return duo;
z_d("57.7");
this.group = group;
var DS = style===false?{}:zim.getStyle("Panel", this.group, inherit);
if (zot(width)) width=DS.width!=null?DS.width:250;
if (zot(height)) height=DS.height!=null?DS.height:300;
this.zimContainer_constructor(width, height, null, null, false);
this.type = "Panel";
if (zot(titleBar)) titleBar = DS.titleBar!=null?DS.titleBar:"PANEL";
if (zot(titleBarColor)) titleBarColor = DS.titleBarColor!=null?DS.titleBarColor:"#fff";
if (zot(titleBarBackgroundColor)) titleBarBackgroundColor = DS.titleBarBackgroundColor!=null?DS.titleBarBackgroundColor:"#555";
if (zot(titleBarHeight)) titleBarHeight = DS.titleBarHeight!=null?DS.titleBarHeight:30;
if (zot(backgroundColor)) backgroundColor=DS.backgroundColor!=null?DS.backgroundColor:"#eee";
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:"#888";
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:null;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = 1;
if (zot(corner)) corner=DS.corner!=null?DS.corner:5;
if (zot(align)) align=DS.align!=null?DS.align:"left";
if (zot(shadowColor)) shadowColor=DS.shadowColor!=null?DS.shadowColor:"rgba(0,0,0,.3)";
if (zot(shadowBlur)) shadowBlur=DS.shadowBlur!=null?DS.shadowBlur:14;
if (zot(draggable)) draggable = DS.draggable!=null?DS.draggable:false;
if (zot(boundary)) boundary = DS.boundary!=null?DS.boundary:null;
if (zot(arrow)) arrow=DS.arrow!=null?DS.arrow:zim.vee(titleBar);
if (!Array.isArray(corner)) corner = [corner,corner,corner,corner];
var that = this;
var background = this.background = new zim.Rectangle(width, height, backgroundColor, borderColor, borderWidth, corner).addTo(this);
if (shadowColor != -1 && shadowBlur > 0) {
this.background.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
}
var titleBarValue = titleBar; // as we assign the container to titleBar later
var t = zim.Pick.choose(titleBarValue);
var tBarColor = zim.Pick.choose(titleBarColor);
var tBarBackgroundColor = zim.Pick.choose(titleBarBackgroundColor);
var pBackgroundColor = zim.Pick.choose(backgroundColor);
var pBorderColor = zim.Pick.choose(borderColor);
if (typeof t == "string") t = new zim.Label({
text:t, color:tBarColor, size:DS.size!=null?DS.size:20,
backing:"ignore", shadowColor:"ignore", shadowBlur:"ignore", padding:"ignore", backgroundColor:"ignore",
group:this.group
});
var titleBarLabel = that.titleBarLabel = t;
if (zot(tBarBackgroundColor)) tBarBackgroundColor = "rgba(0,0,0,.2)";
that.titleBar = titleBar = new zim.Container(width, titleBarHeight, null, null, false).loc(0,0,that);
var titleBarRect = that.titleBar.backing = new zim.Rectangle(width+borderWidth, titleBarHeight, tBarBackgroundColor, null, null, [corner[0]*.95, corner[1]*.95, 0, 0], true, null, false).center(titleBar);
positionBar();
that.label = t;
that.text = t.text;
this.nextPanel = function(index, event) {
var t = zot(index)||zot(titleBarValue.array)?zim.Pick.choose(titleBarValue):titleBarValue.array[index];
var tBarColor = zot(index)||zot(titleBarColor.array)?zim.Pick.choose(titleBarColor):titleBarColor.array[index];
var tBarBackgroundColor = zot(index)||zot(titleBarBackgroundColor.array)?zim.Pick.choose(titleBarBackgroundColor):titleBarBackgroundColor.array[index];
var pBackgroundColor = zot(index)||zot(backgroundColor.array)?zim.Pick.choose(backgroundColor):backgroundColor.array[index];
var pBorderColor = zot(index)||zot(borderColor.array)?zim.Pick.choose(borderColor):borderColor.array[index];
if (typeof t == "string") t = new zim.Label({
text:t, color:tBarColor, size:DS.size!=null?DS.size:20,
backing:"ignore", shadowColor:"ignore", shadowBlur:"ignore", padding:"ignore", backgroundColor:"ignore",
group:this.group
});
that.label = t;
that.text = t.text;
titleBarLabel.removeFrom();
titleBarLabel = that.titleBarLabel = t;
positionBar();
titleBarRect.color = tBarBackgroundColor;
that.background.color = pBackgroundColor;
that.background.borderColor = pBorderColor;
if (event) that.dispatchEvent("change");
if (!OPTIMIZE && that.stage) that.stage.update();
}
function positionBar() {
if (align=="right") titleBarLabel.center(titleBar).pos(Math.max(corner[0]/2, 10), null, true);
else if (align=="center" || align=="middle") titleBarLabel.center(titleBar);
else titleBarLabel.center(titleBar).loc(Math.max(corner[0]/2, 10));
titleBarLabel.mov(0,2);
}
if (draggable) {
titleBar.cursor = "pointer";
titleBar.on("mousedown", function() {
that.drag({rect:boundary, currentTarget:true});
});
titleBar.on("pressup", function() {
that.noDrag();
});
}
if (arrow > 0) {
var next = that.arrow = new zim.Shape(-20,-20,40,40,null,false);
next.graphics.f(titleBarColor).p("AiJieIETCeIkTCfg"); // width about 90 reg in middle
next.centerReg(titleBar).scaleTo(titleBar, null, 70).alp(.8).hov(1).expand();
if (align=="right") next.pos(Math.max(corner[1]/2, 10));
else next.pos(Math.max(corner[1]/2, 10), null, true);
next.cursor = "pointer";
next.on((!zns?ACTIONEVENT=="mousedown":zim.ACTIONEVENT=="mousedown")?"mousedown":"click", function(){
that.nextPanel();
that.dispatchEvent("change");
});
}
if (!zot(extraButton)) {
var extraButton = that.extraButton = new zim.Button({
label:"R",
width:50,
height:50,
group:"PanelExtra"
}).scaleTo(titleBar, null, 70).centerReg(titleBar).expand();
if (align=="left") {
extraButton.pos(arrow>0?next.x-next.width-15:Math.max(corner[1]/2, 10) );
} else {
extraButton.pos((arrow>0&&align!="center")?next.x+next.width: Math.max(corner[1]/2, 10));
}
}
var overlay = that.overlay = new zim.Rectangle(width, height).alp(.7);
this._enabled = true;
Object.defineProperty(that, 'enabled', {
get: function() {
return that._enabled;
},
set: function(value) {
zenable(that, value);
if (!value) that.overlay.addTo(that);
else that.overlay.removeFrom();
if (!OPTIMIZE && that.stage) that.stage.update();
}
});
if (style!==false) zimStyleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.Toggle(width, height, titleBar?titleBar.clone():"", titleBarColor, titleBarBackgroundColor, titleBarHeight, backgroundColor, borderColor, borderWidth, corner, arrow, align, shadowColor, shadowBlur, draggable, boundary, extraButton, style, this.group, inherit));
}
}
zim.extend(zim.Panel, zim.Container, "clone", "zimContainer", false);
//-57.7
/*--
zim.Pane = function(width, height, label, backgroundColor, color, draggable, resets, modal, corner, backdropColor, shadowColor, shadowBlur, center, displayClose, backdropClose, backing, fadeTime, container, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, close, closeColor, style, group, inherit)
Pane
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Adds a window for alerts, etc.
You need to call the pane.show() to show the pane and pane.hide() to hide it.
You do not need to add it to the stage - it adds itself centered.
You can change the x and y (the origin and registration point are in the middle).
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var pane = new Pane(300, 200, "Watch out!", "#CCC");
pane.show(); // pressing anywhere will close pane (see parameters for options)
END EXAMPLE
EXAMPLE
var pane = new Pane({width:600, height:250, modal:false, displayClose:false});
var cancel = new Button(220, 100, "CANCEL", "red").center(pane).mov(-130);
var confirm = new Button(220, 100, "CONFIRM", "green").center(pane).mov(130);
cancel.on("click", function() {pane.hide();});
confirm.on("click", function() {zgo("http://zimjs.com")});
pane.show(); // pressing anywhere will close pane (see parameters for options)
// custom backing with ZIM Pizzazz 3
// up top link to https://d309knd7es5f10.cloudfront.net/pizzazz_03.js
new Pane({
label:new Label({color:white, text:"STOP", size:50}),
backing:pizzazz.makePattern({
type:"stripes",
colors:series(red,black),
rows:20
}).alp(.8)
}).show();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - (default 200) width of pane
height - (default 200) height of pane
label - (default null) an optional ZIM Label (or text for default label properties)
backgroundColor - (default "white") a css color for the background of the Pane
color - (default "black") a css color for the text color of the Pane
draggable - (default false) pass in true to drag the pane
resets - (default true) resets position to start on re-open - set to false to keep last position
modal - (default true) pane will close when user clicks off the pane - set to false to keep pane open
corner - (default 20) is the corner radius - set to 0 for no corner
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
backdropColor - (default rgba(0,0,0,.2)) the color of the background that fills the stage
shadowColor - (default rgba(0,0,0,.3)) set to -1 for no shadow
shadowBlur - (default 20) how blurred the shadow is if shadow is set
center - (default true) centers the pane
if center is false you will have to set x and y for the pane
the registration point and the origin inside the pane is in the center
you can adjust the label placement by changing its x and y or registration point
displayClose - (default true) closes the Pane if display backing is pressed
if draggable is set to true, displayClose will automatically be set to false
backdropClose - (default true) closes the Pane if backdrop is pressed
backing - (default null) a Display object for the backing of the pane (eg. Shape, Bitmap, Container, Sprite)
see ZIM Pizzazz module for a fun set of Shapes like Boomerangs, Ovals, Lightning Bolts, etc.
as well as patterned backings using Pizzazz 3
fadeTime - (default 0) milliseconds to fade in and out
container - (default - the default stage) container for the pane
titleBar - (default null - no titleBar) a String or ZIM Label title for the pane that will be presented on a titleBar across the top
titleBarColor - (default "black") the color of the titleBar text if a titleBar is requested
titleBarBackgroundColor - (default "rgba(0,0,0,.2)") the background color of the titleBar if a titleBar is requested
titleBarHeight - (default fit label) the height of the titleBar if a titleBar is requested
close - (default false) - a close X for the top right corner that closes the pane when pressed
closeColor - (default #555) - the color of the close X if close is requested
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
show() - shows the pane (returns the pane for chaining)
hide(callEvent) - hides the pane - callEvent defaults to false - set to true to also call close event
toggle(state - default null) - shows if hidden and hides if showing (returns the pane for chaining)
or pass in true to show pane or false to hide pane
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied (returns the new pane for chaining)
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
backing - or display - reference to the pane box
text - gives access to the label text
label - gives access to the label
titleBar - gives access to the titleBar Container - which also has a background property
titleBarLabel - gives access to the titleBar label
toggled - read-only Boolean property as to whether pane is showing
close - access to the ZIM Shape if there is a close X
backdrop - reference to the backdrop that covers the stage
container - get or set the container the pane will be added to
resetX - if reset is true you can dynamically adjust the position if needed
resetY - and the y position for reset...
enabled - set to false to disable component
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
OPTIMIZED
This component is affected by the general OPTIMIZE setting (default is false)
if set to true, you will have to stage.update() after setting certain properties
and stage.update() in change event to see component change its graphics
ACTIONEVENT
This component is affected by the general ACTIONEVENT setting
The default is "mousedown" - if set to something else the component will act on click (press)
EVENTS
dispatches a "close" event when closed by clicking on backing, display, close, etc. when applicable
dispatches a "fadedin" event if fadeTime is set and pane has finished its fade in animation
dispatches a "fadedout" event if fadeTime is set and pane has finished its fade out animation
ALSO: See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+58
zim.Pane = function(width, height, label, backgroundColor, color, draggable, resets, modal, corner, backdropColor, shadowColor, shadowBlur, center, displayClose, backdropClose, backing, fadeTime, container, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, close, closeColor, style, group, inherit) {
var sig = "width, height, label, backgroundColor, color, draggable, resets, modal, corner, backdropColor, shadowColor, shadowBlur, center, displayClose, backdropClose, backing, fadeTime, container, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, close, closeColor, style, group, inherit";
var duo; if (duo = zob(zim.Pane, arguments, sig, this)) return duo;
z_d("58");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "Pane";
var mess = "zim display - Pane(): Please pass in a reference to a container with bounds set as first parameter";
if (zot(container)) {
if (zimDefaultFrame) {
container = zimDefaultFrame.stage;
} else {
zog(mess);
return;
}
} else if (!container.getBounds) {
zog(mess);
return;
} else if (zot(container.getStage)) {
zog("zim display - Pane(): The container must have a stage property");
return;
}
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(width)) width=DS.width!=null?DS.width:200;
if (zot(height)) height=DS.height!=null?DS.height:200;
if (zot(label)) label = DS.label!=null?DS.label:null;
if (typeof label === "string" || typeof label === "number") label = new zim.Label({
text:label, size:DS.size!=null?DS.size:40, align:DS.align!=null?DS.align:"center", valign:DS.valign!=null?DS.valign:"center", color:DS.color!=null?DS.color:color,
backing:"ignore", shadowColor:"ignore", shadowBlur:"ignore", padding:"ignore", backgroundColor:"ignore",
group:this.group
});
if (zot(backgroundColor)) backgroundColor=DS.backgroundColor!=null?DS.backgroundColor:"white";
if (zot(draggable)) draggable=DS.draggable!=null?DS.draggable:false;
if (zot(resets)) resets=DS.resets!=null?DS.resets:true;
if (zot(modal)) modal=DS.modal!=null?DS.modal:true;
if (zot(corner)) corner=DS.corner!=null?DS.corner:20;
if (zot(titleBar)) titleBar = DS.titleBar!=null?DS.titleBar:null;
if (zot(titleBarColor)) titleBarColor = DS.titleBarColor!=null?DS.titleBarColor:null;
if (zot(titleBarBackgroundColor)) titleBarBackgroundColor = DS.titleBarBackgroundColor!=null?DS.titleBarBackgroundColor:null;
if (zot(titleBarHeight)) titleBarHeight = DS.titleBarHeight!=null?DS.titleBarHeight:null;
if (zot(backdropColor)) backdropColor=DS.backdropColor!=null?DS.backdropColor:"rgba(0,0,0,.2)";
if (zot(shadowColor)) shadowColor=DS.shadowColor!=null?DS.shadowColor:"rgba(0,0,0,.3)";
if (zot(shadowBlur)) shadowBlur=DS.shadowBlur!=null?DS.shadowBlur:20;
if (zot(center)) center=DS.center!=null?DS.center:true;
if (zot(displayClose)) displayClose=DS.displayClose!=null?DS.displayClose:true;
if (draggable) displayClose = false;
if (zot(backdropClose)) backdropClose=DS.backdropClose!=null?DS.backdropClose:true;
if (zot(fadeTime)) fadeTime=DS.fadeTime!=null?DS.fadeTime:0;
if (zot(close)) close=DS.close!=null?DS.close:false;
if (zot(closeColor)) closeColor=DS.closeColor!=null?DS.closeColor:"#555";
var backdrop = this.backdrop = new zim.Shape({style:false});
backdrop.type = "CreateJS_Shape";
// make a big backing that closes the pane when clicked
// could also provide a close button
var g = backdrop.graphics;
g.f(backdropColor);
g.drawRect(-5000,-5000,10000,10000);
// makes it seem like the pane has the dimensions of the display
this.setBounds(-width/2,-height/2, width, height);
var that = this;
that.container = container;
backdrop.on((!zns?ACTIONEVENT=="mousedown":zim.ACTIONEVENT=="mousedown")?"mousedown":"click", backdropClose?closePane:function(e){e.stopImmediatePropagation();});
var htmlList = new zim.Dictionary(true);
function closePane(e) {
removePane();
that.container.stage.update();
that.dispatchEvent("close");
e.stopImmediatePropagation();
};
backdrop.on("mousedown", function(e) {
e.stopImmediatePropagation();
});
if (modal) this.addChild(backdrop);
var display;
if (zot(backing)) {
display = this.backing = this.display = new zim.Rectangle({
width:width, height:height, color:backgroundColor, corner:corner, style:false
});
} else {
if (backing.type == "Pattern") {
var pattern = backing;
// width, height, color, borderColor, borderWidth, corner, dashed, strokeObj, style, group, inherit
display = new zim.Rectangle(width, height, backgroundColor, null, null, corner, null, null, false);
pattern.centerReg(display);
pattern.setMask(display.shape);
} else {
display = backing;
}
that.display = that.backing = display;
}
if (displayClose) {
display.cursor = "pointer";
display.on((!zns?ACTIONEVENT=="mousedown":zim.ACTIONEVENT=="mousedown")?"mousedown":"click", closePane);
}
if (shadowColor != -1 && shadowBlur > 0) display.shadow = new createjs.Shadow(shadowColor, 8, 8, shadowBlur);
display.on("click", function(e) {
// stops the click from going through the display to the background
e.stopImmediatePropagation();
});
this.resetX; this.resetY;
if (draggable) {
display.cursor = "pointer";
var diffX, diffY;
var stage;
display.on("mousedown", function(e) {
stage = e.target.stage;
if (isNaN(that.resetX)) that.resetX = that.x;
if (isNaN(that.resetY)) that.resetY = that.y;
diffX = e.stageX/zim.scaX - that.x;
diffY = e.stageY/zim.scaY - that.y;
display.cursor = "pointer";
});
display.on("pressmove", function(e) {
var p = checkBounds(e.stageX/zim.scaX-diffX, e.stageY/zim.scaY-diffY);
that.x = p.x;
that.y = p.y;
var ch;
for (var i=0; i 0) {
that.animate({obj:{alpha:0}, time:fadeTime, call:function(){
end();
that.dispatchEvent("fadedout");
}});
} else {
end();
}
function end() {
that.container.removeChild(that);
var ch;
for (var i=0; i=0; i--) { // remove textareas and loaders second
ch = that.getChildAt(i);
if (ch.type == "TextArea" || ch.type == "Loader" || ch.type == "Tag") {
that.removeChild(ch);
}
}
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE))) that.container.stage.update();
if (resets) {
if (!isNaN(that.resetX)) that.x = that.resetX;
if (!isNaN(that.resetY)) that.y = that.resetY;
}
if (that.zimAccessibility) {
var a = that.zimAccessibility;
a.resize(that);
if (accessibilityClicker) accessibilityClicker.focus();
else that.zimTabTag.nextSibling.focus();
setTimeout(function() {a.talk("Pane has been closed.");}, 50);
}
}
}
var accessibilityClicker;
this.show = function() {
if (center) {
if (isNaN(that.resetX)) {
that.x = (that.container.getBounds().width) /2;
that.y = (that.container.getBounds().height) /2;
}
}
that.container.addChild(that);
for (var i=0; i 0) {
that.alpha = 0;
that.animate({
props:{alpha:1},
time:fadeTime,
call:function(){
that.dispatchEvent("fadedin");
}
});
} else {
if (that.container.stage) that.container.stage.update();
}
if (that.zimAccessibility) {
var a = that.zimAccessibility;
setTimeout(function(){if (a.activatedObject) accessibilityClicker = a.activatedObject.zimTabTag;}, 50);
a.resize(that);
a.tabIndex = that.zimTabIndex;
}
that.toggled = true;
return that;
}
function checkBounds(x,y) {
x = Math.max(width/2, Math.min(that.container.getBounds().width-width/2, x));
y = Math.max(height/2, Math.min(that.container.getBounds().height-height/2, y));
return {x:x,y:y}
}
this.toggle = function(state) {
if (state===true) that.show();
else if (state===false) that.hide();
else if (that.container.contains(that)) that.hide();
else that.show();
return that;
}
if (style!==false) zimStyleTransforms(this, DS);
this.clone = function() {
var lX = label.x; // new Panes automatically center the label
var lY = label.y;
var p2 = that.cloneProps(new zim.Pane(width, height, label.clone(), backgroundColor, color, draggable, resets, modal, corner, backdropColor, shadowColor, shadowBlur, center, displayClose, backdropClose, zot(backing)?backing.clone():null, fadeTime, that.container, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, close, closeColor, style, this.group, inherit));
p2.label.x = lX;
p2.label.y = lY;
return p2;
}
}
zim.extend(zim.Pane, zim.Container, "clone", "zimContainer", false);
//-58
/*--
zim.Window = function(width, height, backgroundColor, borderColor, borderWidth, padding, corner, swipe, scrollBarActive, scrollBarDrag, scrollBarColor, scrollBarAlpha, scrollBarFade, scrollBarH, scrollBarV, slide, slideDamp, slideSnap, interactive, shadowColor, shadowBlur, paddingHorizontal, paddingVertical, scrollWheel, damp, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, draggable, boundary, onTop, close, closeColor, cancelCurrentDrag, fullSize, fullSizeColor, resizeHandle, style, group, inherit)
Window
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Adds a window for content that can be swiped and scrolled.
NOTE: if zim namespace zns = true then this overwrites a JS Window - so the JS Window is stored as document.window
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var win = new Window({
height:300,
interactive:false,
padding:0,
slideDamp:.2
});
var container = new Container(); // make some content
var c; spacing = 10;
for (var i=0; i<4; i++) {
c = frame.makeCircles();
c.x = win.width/2;
c.y = c.width/2 + (c.width+spacing)*i;
container.addChild(c);
}
win.add(container); // add the content to the window
win.center(stage);
stage.update();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - (default 300) the width of the window
height - (default 200) the height of window - including the titleBar if there is a titleBar
backgroundColor - (default #333) background color (use clear - or "rbga(0,0,0,0)" for no background)
borderColor - (default #999) border color
borderWidth - (default 1) the thickness of the border
padding - (default 0) places the content in from edges of border (see paddingHorizontal and paddingVertical)
padding is ignored if content x and y not 0 - and really only works on top left - so more like an indent
corner - (default 0) is the rounded corner of the window (does not accept corner array - scrollBars are too complicated)
swipe - (default auto/true) the direction for swiping set to none / false for no swiping
also can set swipe to just vertical or horizontal
scrollBarActive - (default true) shows scrollBar (set to false to not)
scrollBarDrag - (default false) set to true to be able to drag the scrollBar
scrollBarColor - (default borderColor) the color of the scrollBar
scrollBarAlpha - (default .3) the transparency of the scrollBar
scrollBarFade - (default true) fades scrollBar unless being used
scrollBarH - (default true) if scrolling in horizontal is needed then show scrollBar
scrollBarV - (default true) if scrolling in vertical is needed then show scrollBar
slide - (default true) Boolean to throw the content when drag/swipe released
slideDamp - (default .6) amount the slide damps when let go 1 for instant, .01 for long slide, etc.
slideSnap - (default "vertical") "auto" / true, "none" / false, "horizontal"
slides past bounds and then snaps back to bounds when released
vertical snaps when dragging up and down but not if dragging horizontal
interactive - (default true) allows interaction with content in window
set to false and whole window will be swipeable but not interactive inside
shadowColor - (default rgba(0,0,0,.3)) the color of the shadow
shadowBlur - (default 20) set shadowBlur to -1 for no drop shadow
paddingHorizontal - (default padding) places content in from left and right (ignored if content x not 0)
paddingVertical - (default padding) places content in from top and bottom (ignored if content y not 0)
scrollWheel - (default true) scroll vertically with scrollWheel
damp - (default null) set to .1 for instance to damp the scrolling
titleBar - (default null - no titleBar) a String or ZIM Label title for the window that will be presented on a titleBar across the top
titleBarColor - (default "black") the text color of the titleBar if a titleBar is requested
titleBarBackgroundColor - (default "rgba(0,0,0,.2)") the background color of the titleBar if a titleBar is requested
titleBarHeight - (default fit label) the height of the titleBar if a titleBar is requested
draggable - (default true if titleBar) set to false to not allow dragging titleBar to drag window
boundary - (default null) set to ZIM Boundary() object - or CreateJS.rectangle()
onTop - (default true) set to false to not bring Window to top of container when dragging
close - (default false) - a close X for the top right corner that closes the window when pressed
closeColor - (default #555) - the color of the close X if close is requested
cancelCurrentDrag - (default false) - set to true to cancel window dragging when document window loses focus
this functionality seems to work except if ZIM is being used with Animate - so we have left it turned off by default
fullSize - (default false) - set to true to add a fullsize icon to the titleBar
to let user increase the size of the window to the frame - will turn into a reduce size icon
fullSizeColor - (default #555) - the color of the fullSize icon
resizeHandle - (default false) - set to true to rollover bottom right corner to resize window with resizeHandle
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
add(obj, replace) - adds obj to content container of window (at padding) must have bounds set
it is best to position and size obj first before adding
otherwise if adjusting to outside current content size then call update()
replace defaults to false and if set to true, removes all content then adds the obj.
returns window for chaining
remove(obj) - removes object from content container of window and updates - returns window for chaining
removeAll() - removes all objects from content container of window and updates - returns window for chaining
resize(width, height) - resizes the Window without scaling the content (also calls update() for scroll update)
width and height are optional - returns window for chaining
update() - resets window scrolling if perhaps the content gets bigger or smaller
cancelCurrentDrag() - stop current drag on window - but add dragging back again for next drag
clone(recursive) - makes a copy with properties such as x, y, etc. also copied
recursive (default true) clones the window content as well (set to false to not clone content)
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
** see also the resize(width, height) method to resize the window without resizing the content
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
backing - CreateJS Shape used for backing of Window
content - ZIM Container used to hold added content
scrollBar - data object that holds the following properties (with defaults):
you can set after object is made...
scrollBar.horizontal = zim Shape // the horizontal scrollBar rectangle shape
scrollBar.vertical = zim Shape // the vertical scrollBar rectangle shape
scrollBar.color = borderColor; // the color of the scrollBar
scrollBar.size = 6; // the width if vertical or the height if horizontal
scrollBar.minSize = 12; // for the height if vertical or the width if horizontal
scrollBar.spacing = 3 + size + borderWidth / 2;
scrollBar.margin = 0; // adds extra space only at end by scrollBars
scrollBar.corner = scrollBar.size / 2;
scrollBar.showTime = 500; // ms to fade in
scrollBar.fadeTime = 3000; // ms to fade out
scrollX - gets and sets the content x position in the window (this will be negative)
scrollY - gets and sets the content y position in the window (this will be negative)
scrollXMax - gets the max we can scroll in x based on content width - window width (plus padding and margin)
scrollYMax - gets the max we can scroll in y based on content height - window height (plus padding and margin)
titleBar - access to the ZIM Container for the titleBar if there is a titleBar also has a backing property
titleBarLabel - access to the ZIM Label of the titleBar if there is a titleBar
close - access to the ZIM Shape if there is a close X
resizeHandle - access the ZIM Rectangle that makes up the resizeHandle when resizeHandle parameter is set to true
resizeHandle.removeFrom() would stop resize from being available and resizeHandle.addTo(window) would activate it again
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
dispatches a "select" event when clicked on in a traditional manner (fast click with little movement)
dispatches a "hoverover" event when rolled on without moving for 300 ms
dispatches a "hoverout" event when not hovering due to movement or mouseout on the window
dispatches a "scrolling" event when the window scrolls
dispatches a "close" event when the window is closed with the x on the titleBar if there is a titleBar
ALSO: See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+58.1
zim.Window = function(width, height, backgroundColor, borderColor, borderWidth, padding, corner, swipe, scrollBarActive, scrollBarDrag, scrollBarColor, scrollBarAlpha, scrollBarFade, scrollBarH, scrollBarV, slide, slideDamp, slideSnap, interactive, shadowColor, shadowBlur, paddingHorizontal, paddingVertical, scrollWheel, damp, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, draggable, boundary, onTop, close, closeColor, cancelCurrentDrag, fullSize, fullSizeColor, resizeHandle, style, group, inherit) {
var sig = "width, height, backgroundColor, borderColor, borderWidth, padding, corner, swipe, scrollBarActive, scrollBarDrag, scrollBarColor, scrollBarAlpha, scrollBarFade, scrollBarH, scrollBarV, slide, slideDamp, slideSnap, interactive, shadowColor, shadowBlur, paddingHorizontal, paddingVertical, scrollWheel, damp, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, draggable, boundary, onTop, close, closeColor, cancelCurrentDrag, fullSize, fullSizeColor, resizeHandle, style, group, inherit";
var duo; if (duo = zob(zim.Window, arguments, sig, this)) return duo;
z_d("58.1");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "Window";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(width)) width=DS.width!=null?DS.width:300;
if (zot(height)) height=DS.height!=null?DS.height:200;
if (zot(backgroundColor)) backgroundColor=DS.backgroundColor!=null?DS.backgroundColor:"#333";
var originalBorderColor = borderColor;
var originalBorderWidth = borderWidth;
if (zot(borderColor)) borderColor=DS.borderColor!=null?DS.borderColor:"#999";
if (zot(borderWidth)) borderWidth=DS.borderWidth!=null?DS.borderWidth:1; // 0
if (zot(padding)) padding=DS.padding!=null?DS.padding:0;
if (zot(corner)) corner=DS.corner!=null?DS.corner:0;
if (zot(swipe)) swipe=DS.swipe!=null?DS.swipe:true; // true / auto, vertical, horizontal, false / none
if (zot(scrollBarActive)) scrollBarActive=DS.scrollBarActive!=null?DS.scrollBarActive:true;
if (zot(scrollBarDrag)) scrollBarDrag=DS.scrollBarDrag!=null?DS.scrollBarDrag:false;
if (zot(scrollBarColor)) scrollBarColor=DS.scrollBarColor!=null?DS.scrollBarColor:borderColor;
if (zot(scrollBarAlpha)) scrollBarAlpha=DS.scrollBarAlpha!=null?DS.scrollBarAlpha:.3;
if (zot(scrollBarFade)) scrollBarFade=DS.scrollBarFade!=null?DS.scrollBarFade:true;
if (zot(scrollBarH)) scrollBarH = DS.scrollBarH!=null?DS.scrollBarH:true;
if (zot(scrollBarV)) scrollBarV = DS.scrollBarV!=null?DS.scrollBarV:true;
if (scrollBarDrag) scrollBarFade = DS.scrollBarFade!=null?DS.scrollBarFade:false;
if (zot(slide)) slide=DS.slide!=null?DS.slide:true;
if (zot(slideDamp)) slideDamp=DS.slideDamp!=null?DS.slideDamp:.6;
if (zot(slideSnap)) slideSnap=DS.slideSnap!=null?DS.slideSnap:"vertical"; // true / auto, vertical, horizontal, false / none
if (zot(interactive)) interactive=DS.interactive!=null?DS.interactive:true;
if (zot(shadowColor)) shadowColor=DS.shadowColor!=null?DS.shadowColor:"rgba(0,0,0,.3)";
if (zot(shadowBlur)) shadowBlur=DS.shadowBlur!=null?DS.shadowBlur:20;
if (zot(paddingVertical)) paddingVertical=DS.paddingVertical!=null?DS.paddingVertical:padding;
if (zot(paddingHorizontal)) paddingHorizontal=DS.paddingHorizontal!=null?DS.paddingHorizontal:padding;
if (zot(scrollWheel)) scrollWheel = DS.scrollWheel!=null?DS.scrollWheel:true;
if (zot(titleBar)) titleBar = DS.titleBar!=null?DS.titleBar:null;
if (zot(titleBarColor)) titleBarColor = DS.titleBarColor!=null?DS.titleBarColor:null;
if (zot(titleBarBackgroundColor)) titleBarBackgroundColor = DS.titleBarBackgroundColor!=null?DS.titleBarBackgroundColor:null;
if (zot(titleBarHeight)) titleBarHeight = DS.titleBarHeight!=null?DS.titleBarHeight:null;
if (zot(draggable)) draggable = DS.draggable!=null?DS.draggable:null;
if (zot(boundary)) boundary = DS.boundary!=null?DS.boundary:null;
if (zot(onTop)) onTop = DS.onTop!=null?DS.onTop:null;
if (zot(close)) close = DS.close!=null?DS.close:null;
if (zot(closeColor)) closeColor = DS.closeColor!=null?DS.closeColor:null;
if (zot(cancelCurrentDrag)) cancelCurrentDrag = DS.cancelCurrentDrag!=null?DS.cancelCurrentDrag:false;
if (zot(fullSize)) fullSize = DS.fullSize!=null?DS.fullSize:null;
if (zot(fullSizeColor)) fullSizeColor = DS.fullSizeColor!=null?DS.fullSizeColor:null;
if (zot(resizeHandle)) resizeHandle = DS.resizeHandle!=null?DS.resizeHandle:null;
if (titleBar === false) titleBar = null;
if (!zot(titleBar)) {
if (zot(titleBarHeight)) titleBarHeight = 30;
height = height - titleBarHeight;
}
var that = this;
this.scrollX = this.scrollY = this.scrollXMax = this.scrollYMax = 0;
var backing = this.backing = new zim.Shape({style:false});
this.addChild(backing);
var mask = new createjs.Shape();
mask.type = "WindowBacking";
var mg = mask.graphics;
// make the mask in the update function
// when we know if there are vertical and horizontal scrollBars
this.addChild(mask);
var content = this.content = new zim.Container({style:false});
this.addChild(content);
content.mask = mask;
var stage;
if (!interactive) {
// hitArea makes the whole window draggable
// but then you can't interact with the content inside the window
var hitArea = new createjs.Shape();
}
if (borderWidth > 0) {
var border = new createjs.Shape();
this.addChild(border);
}
var titleBarCorner = titleBar?0:corner;
// we call this function at start and when resize() is called to resize the window without scaling content
function sizeWindow() {
that.setBounds(0,0,width,height);
backing.graphics.c().f(backgroundColor).rc(0,0,width,height,titleBarCorner,titleBarCorner,corner,corner);
if (shadowColor != -1 && shadowBlur > 0) backing.shadow = new createjs.Shadow(shadowColor, 4, 4, shadowBlur);
if (borderWidth > 0) {
if (corner) {
border.graphics.c().s(borderColor).ss(borderWidth, "square", "miter").rc(0,0,width,height,titleBarCorner,titleBarCorner,corner,corner);
} else {
border.graphics.c().s(borderColor).ss(borderWidth, "square", "miter").dr(0,0,width,height);
}
}
if (!zot(titleBarRect)) {
titleBarRect = titleBar.backing.widthOnly = that.width;
that.setBounds(0,-titleBarHeight,that.width,height+titleBarHeight);
}
if (that.close) {
if (titleBar) close.pos({x:width-Math.max(corner/2, 10)-close.width/2, y:titleBarHeight/2, reg:true});
else close.pos((Math.max(corner/2, 10))/2, close.height/2, true, false, that);
}
if (that.fullSize) {
fullSize.pos({x:width-Math.max(corner/2, 10)-fullSize.width/2, y:titleBarHeight/2, reg:true});
if (that.close) fullSize.mov(-close.width-10);
}
}
sizeWindow();
// this exposes an scrollBar data object so creators can adjust scrollBar properties
// note that these properties are set dynamically in the update function
var scrollBar = this.scrollBar = {}; // data object to expose scrollBar properties
scrollBar.color = scrollBarColor;
scrollBar.size = 6;
scrollBar.minSize = scrollBar.size*2; // if vertical scroll, this is vertical minSize where size is horizontal size
scrollBar.spacing = 3.5 + borderWidth / 2;
scrollBar.margin = 0;
scrollBar.corner = scrollBar.size / 2;
scrollBar.showTime = 500;
scrollBar.fadeTime = 3000;
if (scrollBarActive) {
var hscrollBar = scrollBar.horizontal = new zim.Shape({style:false});
var hg = hscrollBar.graphics;
hscrollBar.alpha = scrollBarAlpha;
this.addChild(hscrollBar);
if (scrollBarDrag) hscrollBar.drag({localBounds: true});
var vscrollBar = scrollBar.vertical = new zim.Shape({style:false});
var vg = vscrollBar.graphics;
vscrollBar.alpha = scrollBarAlpha;
this.addChild(vscrollBar);
if (scrollBarDrag) vscrollBar.drag({localBounds: true});
}
var hProportion;
var vProportion;
var hCheck;
var vCheck;
var gap;
var contentWidth;
var contentHeight;
var hEvent;
var vEvent;
var dTimeout;
this.update = function() {
if (scrollBarActive) {
// clear the scrollBars and remake anytime this function is called
// as these may change as people add and remove content to the Window
hg.clear(); // horizontal scrollBar
vg.clear(); // vertical scrollBar
}
// assume no gap at left and top
// gap is applied in x if there is a scroll in y
// gap is applied in y if there is a scroll in x
gap = (scrollBarActive) ? scrollBar.size+scrollBar.spacing*2 : 0;
contentWidth = content.getBounds()?content.getBounds().width:0;
contentHeight = content.getBounds()?content.getBounds().height:0;
// note, the contentWidth and contentHeight include ONE padding
hCheck = (scrollBarH && contentWidth > width-paddingHorizontal && (scrollBarActive || swipe === true || swipe == "auto" || swipe == "horizontal"));
vCheck = (scrollBarV && contentHeight > height-paddingVertical && (scrollBarActive || swipe === true || swipe == "auto" || swipe == "vertical"));
that.scrollXMax = contentWidth+paddingHorizontal*2-width+(vCheck?gap+scrollBar.margin:0);
that.scrollYMax = contentHeight+paddingVertical*2-height+(hCheck?gap+scrollBar.margin:0);
// set mask dynamically as scrollBars may come and go affecting the mask size slightly
mg.clear();
var xx = borderWidth/2;
var yy = borderWidth/2;
var ww = width-((vCheck && scrollBarActive)?scrollBar.size+scrollBar.spacing*2:0)-(vCheck?0:borderWidth);
var hh = height-((hCheck && scrollBarActive)?scrollBar.size+scrollBar.spacing*2:0)-(hCheck?0:borderWidth);
mg.f("rgba(0,0,0,0)").rc(xx,yy,ww,hh,titleBarCorner,titleBarCorner,vCheck&&scrollBarActive?0:corner,hCheck&&scrollBarActive?0:corner);
mask.setBounds(that.getBounds().x,that.getBounds().y,that.getBounds().width, that.getBounds().height);
zim.expand(mask, 0);
if (!interactive) {
hitArea.graphics.c().f("red").dr(xx,yy,ww,hh);
content.hitArea = hitArea;
}
var edgeAdjust = Math.max(corner, Math.min(scrollBar.corner, scrollBar.spacing));
var edgeLeft = edgeAdjust + borderWidth/2;
var edgeRight = edgeAdjust + (vCheck?gap:0) + borderWidth/2;
var edgeTop = edgeAdjust + borderWidth/2;
var edgeBottom = edgeAdjust + (hCheck?gap:0) + borderWidth/2;
if (hCheck && scrollBarActive) {
scrollBarLength = Math.max(scrollBar.minSize, (width-edgeLeft-edgeRight) * (width-edgeLeft-edgeRight) / (contentWidth + paddingHorizontal + scrollBar.margin));
hg.f(scrollBar.color).rr(0,0,scrollBarLength,scrollBar.size,scrollBar.corner);
hscrollBar.x = edgeLeft;
hscrollBar.y = height-scrollBar.size-scrollBar.spacing;
// for swiping window:
hProportion = new zim.Proportion(-that.scrollXMax, 0, edgeLeft, width-scrollBarLength-edgeRight, -1);
if (scrollBarDrag) {
hscrollBar.setBounds(0,0,scrollBarLength,scrollBar.size);
// drag rect for scrollBar
var rect = new createjs.Rectangle(
edgeLeft, hscrollBar.y, width-scrollBarLength-edgeLeft-edgeRight, 0
);
hscrollBar.dragBoundary(rect);
hscrollBar.proportion = new zim.Proportion(
rect.x, rect.x+rect.width, 0, -that.scrollXMax
);
hscrollBar.off("pressmove", hEvent);
hEvent = hscrollBar.on("pressmove", function() {
that.dispatchEvent("scrolling");
if (hitArea) {
// move hitarea to display box
hitArea.x = -content.x;
hitArea.y = -content.y;
}
content.x = hscrollBar.proportion.convert(hscrollBar.x);
});
}
}
if (vCheck && scrollBarActive) {
scrollBarLength = Math.max(scrollBar.minSize, (height-edgeTop-edgeBottom) * (height-edgeTop-edgeBottom) / (contentHeight + paddingVertical + scrollBar.margin));
vg.f(scrollBar.color).rr(0,0,scrollBar.size,scrollBarLength,scrollBar.corner);
vscrollBar.x = width-scrollBar.size-scrollBar.spacing;
vscrollBar.y = edgeTop;
// for swiping window:
vProportion = new zim.Proportion(-that.scrollYMax, 0, edgeTop, height-scrollBarLength-edgeBottom, -1);
if (scrollBarDrag) {
vscrollBar.setBounds(0,0,scrollBar.size,scrollBarLength);
// drag rect for scrollBar
var rect = new createjs.Rectangle(
vscrollBar.x, edgeTop, 0, height-scrollBarLength-edgeTop-edgeBottom
);
vscrollBar.dragBoundary(rect);
vscrollBar.proportion = new zim.Proportion(
rect.y, rect.y+rect.height, 0, -that.scrollYMax
);
vscrollBar.off("pressmove", vEvent);
vEvent = vscrollBar.on("pressmove", function() {
that.dispatchEvent("scrolling");
if (hitArea) {
// move hitarea to display box
hitArea.x = -content.x;
hitArea.y = -content.y;
}
desiredY = content.y = vscrollBar.proportion.convert(vscrollBar.y);
});
}
}
movescrollBars();
clearTimeout(that.d2Timeout);
that.d2Timeout = setTimeout(function(){
if (hscrollBar && hscrollBar.proportion) content.x = hscrollBar.proportion.convert(hscrollBar.x);
if (vscrollBar && vscrollBar.proportion) content.y = vscrollBar.proportion.convert(vscrollBar.y);
}, 50);
clearTimeout(that.dTimeout);
that.dTimeout = setTimeout(function(){setdragBoundary();}, 300);
}
this.resize = function(w, h) {
if (zot(w)) w = width;
if (zot(h)) h = height;
var min = 20;
if (titleBar) min = titleBarLabel.x+titleBarLabel.width+10;
if (w < min) w = min;
if (h < 20) h = 20;
width = w;
height = h;
sizeWindow();
for (var i=0; i 0) {
setTimeout(function(){setdragBoundary();}, 300);
}
}
this.cancelCurrentDrag = function() {
that.content.noDrag();
zim.drag({
obj:content,
currentTarget:true,
localBounds:true,
slide:slide, slideDamp:slideDamp,
slideSnap:(scrollBarH && (swipe===true||swipe=="auto"||swipe=="horizontal")) || (scrollBarV && (swipe===true||swipe=="auto"||swipe=="vertical"))?slideSnap:false
});
if (content.getBounds() && content.getBounds().width > 0) {
setTimeout(function(){setdragBoundary();}, 300);
}
}
// if (interactive) {
this.added(function (_stage) {
_stage.on("stagemousemove", function (e) {
that.windowMouseX = e.stageX/zim.scaX;
that.windowMouseY = e.stageY/zim.scaY;
});
});
// }
if (slide) {
content.on("slidestop", stageUp);
} else {
content.on("mousedown", function() {
content.stage.on("stagemouseup", stageUp, null, true);
});
}
if (cancelCurrentDrag) {
that.blurEvent = document.window.addEventListener("blur", function () {
that.cancelCurrentDrag();
stageUp();
});
}
function stageUp(e) {
zim.Ticker.remove(swipeMovescrollBars);
swipeCheck = false;
if (hCheck) if (scrollBarFade && scrollBarActive) zim.animate(hscrollBar, {alpha:0}, scrollBar.fadeTime);
if (vCheck) if (scrollBarFade && scrollBarActive) zim.animate(vscrollBar, {alpha:0}, scrollBar.fadeTime);
}
if (interactive) {
// dispatches SELECT (click) and HOVEROVER (500 ms) and gives mouseX and mouseY on content
// CLICKS (in the traditional sense rather than a mouseup replacement)
var downLoc;
var downTime;
content.on("mousedown", function(e){stage=e.target.stage; downLoc=e.stageX/zim.scaX; downTime=Date.now();});
content.on("click", function(e){
if (Date.now()-downTime<600 && Math.abs(e.stageX/zim.scaX-downLoc)<5) {
that.contentMouse = content.globalToLocal(e.stageX/zim.scaX, e.stageY/zim.scaY);
that.dispatchEvent("select");
}
});
// HOVER (must stay within thresh pixels for pauseTime ms)
content.on("mouseover", moveOn);
content.on("mouseout", moveOff);
var startTime;
function moveOn() {
startTime=Date.now();
zim.Ticker.add(timeMouse, content.stage);
}
function moveOff() {
if (!hoverOutCalled) {
that.dispatchEvent("hoverout");
hoverOutCalled = true;
}
zim.Ticker.remove(timeMouse);
}
var lastMouseX = 0;
var lastMouseY = 0;
var lastReportX = 0;
var lastReportY = 0;
var pauseTime = 300;
var thresh = 2;
var hoverOutCalled = false;
function timeMouse() {
if (!content.stage) {
if (!hoverOutCalled) {
that.dispatchEvent("hoverout");
hoverOutCalled = true;
}
zim.Ticker.remove(timeMouse);
return;
}
if (Math.abs(lastMouseX-that.windowMouseX) > thresh || Math.abs(lastMouseY-that.windowMouseY) > thresh) {
if (!hoverOutCalled) {
that.dispatchEvent("hoverout");
hoverOutCalled = true;
}
startTime=Date.now();
lastMouseX=that.windowMouseX;
lastMouseY=that.windowMouseY;
} else {
if (Date.now()-startTime > pauseTime) {
if (Math.abs(lastReportX-that.windowMouseX) > thresh || Math.abs(lastReportY-that.windowMouseY) > thresh) {
that.contentMouse = content.globalToLocal(that.windowMouseX, that.windowMouseY);
that.dispatchEvent("hoverover");
lastReportX=that.windowMouseX;
lastReportY=that.windowMouseY;
hoverOutCalled = false;
}
startTime=Date.now();
}
}
}
}
var scrollEvent1;
var scrollEvent2;
var scrollEvent3;
var desiredY = that.scrollY;
if (scrollWheel) {
scrollEvent1 = window.addEventListener("mousewheel", scrollWindow);
scrollEvent2 = window.addEventListener("wheel", scrollWindow);
scrollEvent3 = window.addEventListener("DOMMouseScroll", scrollWindow);
function scrollWindow(e) {
if (vCheck && that.stage && that.hitTestPoint(that.windowMouseX, that.windowMouseY) && that.contains(that.stage.getObjectUnderPoint(that.windowMouseX*zim.scaX, that.windowMouseY*zim.scaY))) {
if (zot(e)) e = event;
var delta = e.detail ? e.detail*(-19) : e.wheelDelta;
if (zot(delta)) delta = e.deltaY*(-19);
desiredY += delta;
desiredY = Math.max(-that.scrollYMax, Math.min(0, desiredY))
if (!damp) {
that.scrollY = desiredY;
content.stage.update();
}
}
}
}
var dampCheck = false;
var dampY;
function makeDamp(obj) {
if (damp && !dampCheck && obj.stage) {
dampCheck = true;
dampY = new zim.Damp(that.scrollY, damp);
zim.Ticker.add(function() {
if (swipeCheck) return;
if (!zot(desiredY)) that.scrollY = dampY.convert(desiredY);
}, obj.stage);
}
}
Object.defineProperty(that, 'scrollX', {
get: function() {
return content.x;
},
set: function(value) {
content.x = value;
if (content.zimDragImmediate) content.zimDragImmediate(content.x, content.y);
movescrollBars();
}
});
Object.defineProperty(that, 'scrollY', {
get: function() {
return content.y;
},
set: function(value) {
content.y = value;
if (content.zimDragImmediate) content.zimDragImmediate(content.x, content.y);
movescrollBars();
}
});
if (style!==false) zimStyleTransforms(this, DS);
this.clone = function(recursive) {
if (zot(recursive)) recursive = true;
var w = that.cloneProps(new zim.Window(width, height, backgroundColor, originalBorderColor, originalBorderWidth, padding, corner, swipe, scrollBarActive, scrollBarDrag, scrollBar.color, scrollBarAlpha, scrollBarFade, scrollBarH, scrollBarV, slide, slideDamp, slideSnap, interactive, shadowColor, shadowBlur, paddingHorizontal, paddingVertical, titleBar, titleBarColor, titleBarBackgroundColor, titleBarHeight, draggable, boundary, onTop, close, closeColor, cancelCurrentDrag, fullSize, fullSizeColor, resizeHandle, style, group, inherit));
if (recursive) {
that.content.cloneChildren(w.content);
w.update();
}
return w;
}
this.dispose = function(a,b,disposing) {
if (scrollWheel) {
window.removeEventListener("mousewheel", scrollEvent1);
window.removeEventListener("wheel", scrollEvent2);
window.removeEventListener("DOMMouseScroll", scrollEvent3);
}
if (that.resizeHandle) that.resizeHandle.removeAllEventListeners();
if (that.blurEvent) document.window.removeEventListener("blur", that.blurEvent);
if (!zot(timeMouse)) zim.Ticker.remove(timeMouse);
if (!zot(swipeMovescrollBars)) zim.Ticker.remove(swipeMovescrollBars);
if (!disposing) this.zimContainer_dispose(true);
return true;
}
}
zim.extend(zim.Window, zim.Container, ["clone", "dispose"], "zimContainer", false);
//-58.1
/*--
zim.Layer = function(width, height, titleBar, titleBarContainer, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, color, rollColor, selectedColor, selectedRollColor, borderWidth, borderColor, dashed, transformObject, titleBarWidth, titleBarHeight, titleBarX, titleBarY, titleBarDraggable, close, closeColor, closeBackgroundColor, closeIndicatorColor, anchor, style, group, inherit)
Layer
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Layer is a ZIM Container with transform controls.
ZIM transform() objects have their mousechildren turned off so they can be dragged and transformed.
This means there can be no interactivity inside the transformed object.
Layer provides a solution to nest transformed objects in transformable containers.
It does so by providing a titleBar that can be used to turn on and off the transform of the container
and allow its contents to be transformed when the transform controls of the Layer are turned off.
This is more than just hiding the transform tools but rather removing and adding them.
The Layer titleBar will always remain visible on the stage
If the Layer is moved (not by its titleBar) so that the titleBar hits the edge,
then the titleBar will become anchored to the edge (unless anchor is set to false)
This creates an independent titleBar that can be moved to any location.
The titleBarPos() method can also be used to separate the titleBar at any time.
Drop the titleBar on the top left corner of the Layer or doubleClick it to snap it back on to the layer
NOTE: Layers can be added to a Transform Manager and saved with the persist sytem.
NOTE: Layers can be added to Layers (nested) along with any other type of DisplayObject content.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
SEE: https://zimjs.com/explore/layer.html
EXAMPLE
// adding the Layers above the content will allow pressing Layer titleBar objects inside other Layers
// adding everything right on the stage would not allow pressing titleBars inside other Layers - either way may be best, depending on content
var content = new Container(stageW, stageH).addTo();
var layers = new Container(stageW, stageH).addTo();
// create an outer layer with two inner layers - one holding a circle and the other two circles
var layer0 = new Layer(800, 500, "LAYER 0", layers).center(content);
var layer1 = new Layer(300, 400, "LAYER 1", layers).loc(50,50,layer0);
var circle1 = new Circle(50, pink).center(layer1).transform({visible:false});
var layer2 = new Layer(300, 400, "LAYER 2", layers).pos(50,50,true,false,layer0);
var circle2 = new Circle(50, green).center(layer2).mov(0, -80).transform({visible:false});
var circle3 = new Circle(50, blue).center(layer2).mov(0, 80).transform({visible:false});
// optionally store transforms
var t = new TransformManager([layer0, layer1, layer2, circle1, circle2, circle3], "layersID");
// t.clearPersist("layersID")
timeout(1000, function () {
layer2.resetTitleBar();
layer2.turnOn();
// if moving manually, must call resize()
layer2.mov(30);
layer2.resize();
stage.update();
});
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - (default 500) the width of the Layer Container
height - (default 500) the height of the Layer Container not including the titleBar (which is not in the Container)
titleBar - (default "LAYER") a String or ZIM Label for the titleBar
titleBarContainer - (default null - ZimDefaultFrame' stage) a container for the titleBar
can group these with other Layers and hide them all by hiding the container for instance
this also can help layer the titleBars above the content
backgroundColor - (default #eee) the background color of the titleBar
rollBackgroundColor - (default #fff) the roll background color of the titleBar
selectedBackgroundColor - (default #666) the selected background color of the titleBar
color - (default #666) the color of the titleBar text
rollColor - (default #666) the roll color of the titleBar text
selectedColor - (default #ddd) the selected color of the titleBar text
borderWidth - (default 1) the width of the ghost outline when the Layer is not selected
to adjust the transform controls border width use the transformObject parameter and set the borderWidth property
borderColor - (default borderColor) the color of the ghost outline when the Layer is not selected
to adjust the transform controls border color use the transformObject parameter and set the borderColor property
dashed - (default true) the dashed of the ghost outline when the Layer is not selected
to adjust the transform controls border dashed use the transformObject parameter and set the dashed property
transformObject - (default {borderColor:selectedBackgroundColor}) any of the transform parameters as an object literal
certain properties are overwritten by Layer as follows:
{events:true, visible:false, ghostColor:borderColor, ghostWidth:borderWidth, ghostDashed:dashed, ghostHidden:true}
use the transformControls.show() to show the transform controls once the Layer is made for instance:
timeout(100, function(){layer.transformControls.show();}); // a timeout is needed as Layer gets created - sorry.
titleBarWidth - (default 100 + 30 if close) the width of the titleBar. 30 pixels will be added if close is true
titleBarHeight - (default 40) the height of the titleBar
titleBarX - (default null) the starting x position of the titleBar - see also titleBarPos() and resetTitleBar() methods
titleBarY - (default null) the starting y position of the titleBar - see also titleBarPos() and resetTitleBar() methods
titleBarDraggable - (default true) set to false to not let the titleBar be dragged.
this is useful with the titleBarPos() to create a stationary menu for the layers - for instance along the edge like tabs
close - (default true) - set to false to not use the close checkbox
WARNING: without the close checkbox, the user may make the layer bigger than the stage and not be able to deselect the layer
closeColor - (default selectedBackgroundColor) the border of the close checkBox
closeBackgroundColor - (default selectedBackgroundColor) the backgroundColor of the close checkBox
closeIndicatorColor - (default selectedColor) the indicator color of the close checkBox
anchor - (default true) set to false to not anchor the titleBar to the edge if dragged with the Layer (not the titleBar)
with anchor true, the user can dock the titleBar to the edges and then drag them to any desired location
the user can snap the titleBar back on the layer by dropping it on the top left corner of the layer or double clicking the titleBar
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
titleBarPos(x, y, right, bottom) - position the titleBar in the titleBarContainer - returns object for chaining
This will undock the titleBar from the Layer so it can be moved independently
unless titleBarDraggable is set to false
See also titleBarX and titleBarY parameters to start titleBars at a certain position
resetTitleBar() - dock the titleBar back on the Layer - returns object for chaining
toggle(state) - toggle the controls or turn on or off the controls by providing a Boolean state - returns object for chaining
resize(dispatch) - resize the Layer and its children if Layer is manually adjusted - returns object for chaining
for instance, layer.x = 10; layer.resize(); otherwise, the transform controls are broken!
normal layer transforming using the controls automatically resize.
Setting dispatch to true will dispatch a "transformed" event
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied (returns the new waiter for chaining)
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
transformControls - the transform transformControls object - see below for a description
anchor - get or set whether the titleBar will anchor to the edges of the titleBarContainer
toggled - read only if Layer has its transform turned on - or use transformControls.visible
use toggle(state) to toggle controls or pass in true for show controls or false for hide controls
titleBar - access to the ZIM Container that holds the titleBar
titleBarDraggable - get or set whether the titleBar can be dragged
use with titleBarPos() to permanently positing the titleBar
checkBox - access to the ZIM CheckBox that shows when the Layer is active and close is true
button - access to the ZIM Button that makes up the titleBar
label - access to the ZIM Label that is on the Button for the titleBar
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the transformControls property described below for more options.
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
TRANSFORM CONTROL OBJECT
Layer receives a transformControls property
This may be slightly delayed as Layer is prepared on stage
var layer = new Layer().center();
timeout(100, function(){zog(layer.transformControls);}); // will probably do the trick
The transformControls property holds the following:
TRANSFORM CONTROL OBJECT PROPERTIES
visible - read only whether the controls are visible
ghost - read only as to whether the ghost outline is showing - set with showGhost and hideGhost
ghostEnabled - read only as to whether the ghost outline will be turned on and off - set with addGhost and removeGhost
scaleControls - reference to the Container that holds the corner boxes for scaling
stretchXControls - reference to the Container that holds the left and right boxes for stretching
stretchYControls - reference to the Container that holds the top and bottom boxes for stretching
rotateControls - reference to the Container that holds the outer circles for rotating
TRANSFORM CONTROL OBJECT METHODS
hide() - hides the controls - returns object for chaining
show() - shows the controls - returns object for chaining
recordData(toJSON) - returns an object with type, x, y, scaleX, scaleY, rotation, skewX, skewY, visible PROPERTIES
if toJSON (default false) is set to true, the return value is a JSON string
setData(data, fromJSON) - sets the properties to match the data object passed in - this should come from recordData()
if fromJSON (default false) is set to true, it will assume a JSON string is passed in as data
returns object for chaining
remove(noHide) - removes the controls - set noHide true if already hidden
add(noShow) - adds the controls back if then have been removed - set noShow true if not wanting to show
allowToggleOn() - sets the show / hide controls on with click
allowToggleOff() - removes the show / hide controls on with click
showGhost() - show the ghost outline - the ghostWidth or ghostColor must be set in initial parameters
hideGhost() - hide the ghost outline
toggleGhost(state) - if ghost is showing will hide ghost and if ghost is hidden will show ghost
or set state to true to show ghost or false to not show ghost
addGhost() - enable ghost outline functionality - the ghostWidth or ghostColor must be set in initial parameters
removeGhost() - disable ghost outline functionality
disable() - may show the controls if visible but cannot use them
enable() - turns the using of the controls back on
resize(dispatch) - call resize if the object is transformed in ways other than with the controls
set dispatch to true to dispatch a "transformed" event - if manually adjusted this will save to TransformManager
EVENTS
dispatches a "transformed" event when being transformed
the transformed event object has a transformType property
the transformType property has values of "size", "move", "rotate", "stretch", "reg", "reset"
the transformType also might be "resize" if resize(true) is called to dispatch a transformed event
the transformed event object also has a pressup property that is true if on pressup and null if from pressmove
dispatches "transformshow" and "transformhide" events for when click to hide or show controls
If TransformManager() is used there are more events available such as "persistset", etc.
See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+58.5
zim.Layer = function(width, height, titleBar, titleBarContainer, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, color, rollColor, selectedColor, selectedRollColor, borderWidth, borderColor, dashed, transformObject, titleBarWidth, titleBarHeight, titleBarX, titleBarY, titleBarDraggable, close, closeColor, closeBackgroundColor, closeIndicatorColor, anchor, style, group, inherit) {
var sig = "width, height, titleBar, titleBarContainer, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, color, rollColor, selectedColor, selectedRollColor, borderWidth, borderColor, dashed, transformObject, titleBarWidth, titleBarHeight, titleBarX, titleBarY, titleBarDraggable, close, closeColor, closeBackgroundColor, closeIndicatorColor, anchor, style, group, inherit";
var duo; if (duo = zob(zim.Layer, arguments, sig, this)) return duo;
z_d("58.5");
this.group = group;
var DS = style===false?{}:zim.getStyle("Layer", this.group, inherit);
if (zot(width)) width=DS.width!=null?DS.width:500;
if (zot(height)) height=DS.height!=null?DS.height:500;
this.zimContainer_constructor(0,0,width,height,false);
this.type = "Layer";
var that = this;
that.distX = 40; // titleBar distance from top left corner of Container
that.distY = 0;
if (zot(titleBar)) titleBar=DS.titleBar!=null?DS.titleBar:"LAYER";
var titleBarOriginal = titleBar;
var titleBarText = titleBar;
var titleBarDefault = true;
if (zot(backgroundColor)) backgroundColor=DS.backgroundColor!=null?DS.backgroundColor:"#eee";
if (zot(rollBackgroundColor)) rollBackgroundColor=DS.rollBackgroundColor!=null?DS.rollBackgroundColor:"#fff";
if (zot(selectedBackgroundColor)) selectedBackgroundColor=DS.selectedBackgroundColor!=null?DS.selectedBackgroundColor:"#666";
if (zot(color)) color=DS.color!=null?DS.color:"#666";
if (zot(rollColor)) rollColor=DS.rollColor!=null?DS.rollColor:"#666";
if (zot(selectedColor)) selectedColor=DS.selectedColor!=null?DS.selectedColor:"#ddd";
if (zot(borderWidth)) borderWidth=DS.borderWidth!=null?DS.borderWidth:1;
if (zot(borderColor)) borderColor=DS.borderColor!=null?DS.borderColor:backgroundColor;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
if (zot(dashed)) dashed=DS.dashed!=null?DS.dashed:true;
if (zot(transformObject)) transformObject=DS.titleBar!=null?DS.titleBar:null;
if (zot(titleBarWidth)) titleBarWidth=DS.titleBarWidth!=null?DS.titleBarWidth:100;
var originalTitleBarWidth = titleBarWidth;
if (zot(titleBarHeight)) titleBarHeight=DS.titleBarHeight!=null?DS.titleBarHeight:40;
if (zot(titleBarX)) titleBarX=DS.titleBarX!=null?DS.titleBarX:null;
if (zot(titleBarY)) titleBarY=DS.titleBarY!=null?DS.titleBarY:null;
if (zot(titleBarDraggable)) titleBarDraggable=DS.titleBarDraggable!=null?DS.titleBarDraggable:true;
if (zot(close)) close=DS.close!=null?DS.close:true;
if (zot(closeColor)) closeColor=DS.closeColor!=null?DS.closeColor:selectedBackgroundColor;
if (zot(closeBackgroundColor)) closeBackgroundColor=DS.closeBackgroundColor!=null?DS.closeBackgroundColor:selectedBackgroundColor;
if (zot(closeIndicatorColor)) closeIndicatorColor=DS.closeIndicatorColor!=null?DS.closeIndicatorColor:selectedColor;
if (zot(anchor)) anchor=DS.anchor!=null?DS.anchor:true;
if (!titleBarDraggable) anchor = false;
that.anchor = anchor;
if (close) titleBarWidth += 30;
transformObject = zim.merge({borderColor:selectedBackgroundColor}, transformObject, {events:true, visible:false, ghostColor:borderColor, ghostWidth:borderWidth, ghostDashed:dashed, ghostHidden:true});
// do the defaultFrame thing for the container
if (zot(titleBarContainer)) titleBarContainer=DS.titleBarContainer!=null?DS.titleBarContainer:null;
if (zot(titleBarContainer)) {
if (zimDefaultFrame) {
titleBarContainer = zimDefaultFrame.stage;
} else {
zog("zim Layer(): Please pass in a reference to a container with bounds set.");
return;
}
}
var downCheck = false;
that.active = false;
that.turnOff = function(noHide, noShow) {
that.active = false;
if (close) that.checkBox.visible = false;
that.transformControls.remove();
that.mouseChildren = true;
that.button.backgroundColor = backgroundColor;
that.button.rollBackgroundColor = rollBackgroundColor;
that.button.color = color;
that.button.rollColor = color;
that.transformControls.allowToggleOff();
if (that.resizeChildren) that.resizeChildren();
}
that.turnOn = function() {
that.active = true;
if (close) {
that.checkBox.visible = true;
that.checkBox.checked = true;
}
that.button.backgroundColor = selectedBackgroundColor;
that.button.rollBackgroundColor = selectedBackgroundColor;
that.button.color = selectedColor;
that.button.rollColor = selectedColor;
that.mouseChildren = false;
that.transformControls.add();
that.transformControls.allowToggleOn();
}
var stage;
that.titleBarPos = function(x, y) {
if (!that.titleBar) return;
if (that.titleBar.pos) {
that.titleBar.pos(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9]); // ES6 wish
stage.update();
} else {
that.distX = x;
that.distY = y;
}
titleBarDefault = false;
return that;
}
var lastVisible = that.visible;
that.visible = false;
var firstControl;
this.added(function (theStage) {
that.transform(transformObject); // in case persist is set do this first and wait a little bit with visible false
if (borderWidth >= 0) that.transformControls.hideGhost();
zim.timeout(50, function () {
function firstPoint() {return that.localToLocal(0,0,titleBarContainer);}
that.visible = lastVisible;
if (borderWidth >= 0) {
zim.timeout(100, function(){
that.transformControls.showGhost();
stage.update();
});
}
stage = theStage;
var titleBar = that.titleBar = new zim.Container(titleBarWidth, titleBarHeight)
.reg(0,titleBarHeight)
.loc(that, null, titleBarContainer)
.mov(that.distX,that.distY);
if (titleBarDraggable) titleBar.drag({all:true, boundary:new zim.Boundary(0,titleBarHeight,titleBarContainer.width-titleBarWidth,titleBarContainer.height-titleBarHeight), localBounds:true});
if (that.distX != 40 || that.distY !=0) {
titleBar.pos(that.distX, that.distY);
}
if (close) {
that.checkBox = new zim.CheckBox({
borderColor:closeColor,
backgroundColor:closeBackgroundColor,
indicatorColor:closeIndicatorColor,
size:20, startChecked:true
}).center(titleBar).pos(0, null, true).change(function () {
that.turnOff(true, true);
});
that.checkBox.visible = false;
}
titleBar.mouseChildren = true;
titleBar.layer = that;
that.resetTitleBar = function() {
that.distX = 40;
that.distY = 0;
titleBarDefault = true;
that.move(true);
stage.update();
}
if (typeof titleBarText === "string" || typeof titleBarText === "number") titleBarText = new zim.Label({
text:titleBarText, color:color, rollColor:rollColor, size:DS.size!=null?DS.size:18,
group:this.group
});
that.label = titleBarText;
that.label.center(titleBar);
that.button = new zim.Button({
shadowBlur:-1,
width:originalTitleBarWidth, height:titleBarHeight-1, label:that.label,
color:color,
rollColor:rollColor,
backgroundColor:backgroundColor,
rollBackgroundColor:rollBackgroundColor,
corner:(DS.corner!=null?DS.corner:0),
inherit:zim.copy(DS)
}).addTo(titleBar);
that.button.on("mousedown", function () {
downCheck = true;
// all other layers get turned off
titleBarContainer.loop(function (bar) {
if (bar && bar != titleBar && bar.layer && bar.layer.turnOff && bar.layer.active) bar.layer.turnOff(true, true);
});
if (!that.active) that.turnOn();
titleBar.top();
});
that.button.on("pressmove", function(){matchLocation()});
that.button.on("pressup", function () {
matchLocation(true);
var point = that.localToLocal(0, 0, titleBarContainer);
that.distX = titleBar.x-point.x;
that.distY = titleBar.y-point.y;
titleBar.top();
downCheck = false;
if (!edgeCheck() && titleBarDraggable) {
var point = that.localToGlobal(0,0);
if (that.button.hitTestPoint(point.x, point.y)) that.resetTitleBar();
}
});
function matchLocation(dispatch) {
if (titleBarDefault && titleBarDraggable) {
var desiredTopLeft = titleBarContainer.localToLocal(titleBar.x-that.distX, titleBar.y-that.distY, that.parent);
var regPoint = that.localToLocal(that.regX, that.regY, that.parent);
var topLeft = that.localToLocal(0,0,that.parent);
that.x = desiredTopLeft.x + (regPoint.x-topLeft.x);
that.y = desiredTopLeft.y + (regPoint.y-topLeft.y);
that.transformControls.resize(dispatch); // TransformManager saves all objects any time a single object changes
recursiveLocation(that);
}
}
function recursiveLocation(obj) {
obj.loop(function (o) {
if (o.type == "Layer") {
if (that.titleBarDraggable) o.move();
if (o.transformControls.ghost) o.transformControls.resize(); // to move ghost
recursiveLocation(o);
}
});
}
that.button.on("dblclick", function () {
if (titleBarDraggable) that.resetTitleBar();
});
that.turnOff();
that.on("transformed", function (e) {
if (e.transformType=="move" || e.transformType=="size" || e.transformType=="stretch" || e.transformType=="rotate") {
if (titleBarDraggable) that.move();
recursiveLocation(that);
}
});
function edgeCheck() {
if (titleBar.x == 0) return true;
if (titleBar.y == titleBar.height) return true;
if (titleBar.x == titleBarContainer.width-titleBar.width) return true;
if (titleBar.y == titleBarContainer.height) return true;
}
that.move = function(override) {
if (!override && !titleBarDefault && that.anchor) {
if (edgeCheck()) return;
}
titleBar.loc(firstPoint()).mov(that.distX, that.distY);
if (titleBar.x < 0) {titleBarDefault=false; titleBar.x = 0;}
if (titleBar.y < titleBar.height) {titleBarDefault=false; titleBar.y = titleBar.height;}
if (titleBar.x > titleBarContainer.width-titleBar.width) {titleBarDefault=false; titleBar.x = titleBarContainer.width-titleBar.width;}
if (titleBar.y > titleBarContainer.height) {titleBarDefault=false; titleBar.y =titleBarContainer.height}
if (!that.anchor) titleBarDefault = true;
}
that.on("transformhide", function() {
that.turnOff(true, true);
titleBarContainer.loop(function (bar) {
if (bar && bar != titleBar && bar.layer && bar.layer.turnOff && bar.layer.active) bar.layer.turnOff();
});
});
that.resizeChildren = function(dispatch) {
that.transformControls.resize(dispatch);
// if (that.transformControls.visible) that.transformControls.hide();
that.loop(function (obj) {
if (obj.transformControls) {
if (obj.transformControls.visible) obj.transformControls.hide();
if (obj.type == "Layer") {
obj.resizeChildren();
} else {
obj.transformControls.resize();
}
}
});
}
that.resize = function(dispatch) {
that.move();
that.resizeChildren(dispatch);
return that;
}
that.toggled = false;
function setToggled() {
if (that.toggled) {
titleBarContainer.loop(function (bar) {
if (bar && bar != titleBar && bar.layer && bar.layer.turnOff && bar.layer.active) bar.layer.turnOff();
});
that.turnOn();
} else {
titleBar.top();
that.turnOff();
titleBarContainer.loop(function (bar) {
if (bar && bar != titleBar && bar.layer && bar.layer.turnOff && bar.layer.active) bar.layer.turnOff();
});
}
if (that.stage) that.stage.update();
}
that.toggle = function(state) {
if (zot(state)) {
that.toggled = !that.toggled;
} else {
that.toggled = state;
}
setToggled();
return that;
}
Object.defineProperty(that, 'titleBarDraggable', {
get: function() {
return titleBarDraggable;
},
set: function(value) {
titleBarDraggable = value;
if (titleBarDraggable) titleBar.drag({all:true, boundary:zim.Boundary(0,40,titleBarContainer.width-titleBarWidth,titleBarContainer.height-titleBarHeight), localBounds:true})
else titleBar.noDrag();
}
});
stage.on("stagemouseup", function () {
if (that.transformControls.visible) titleBar.top();
});
if (!zot(titleBarX) || !zot(titleBarY)) {
titleBarDefault = false;
var x = !zot(titleBarX)?titleBarX:titleBar.x;
var y = !zot(titleBarY)?titleBarY:titleBar.y-titleBarHeight;
that.titleBarStartX = titleBarX;
that.titleBarStartY = titleBarY;
that.titleBarPos(x,y);
var point = that.parent.localToLocal(that.x, that.y, titleBarContainer);
that.distX = titleBar.x-point.x;
that.distY = titleBar.y-point.y;
}
}); // end timeout
}); // end added
if (style!==false) zimStyleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.Layer(width, height, titleBarOriginal, titleBarContainer, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, color, rollColor, selectedColor, selectedRollColor, borderWidth, borderColor, dashed, transformObject, originalTitleBarWidth, titleBarHeight, titleBarX, titleBarY, titleBarDraggable, close, closeColor, closeBackgroundColor, closeIndicatorColor, anchor, style, this.group, inherit));
}
this.dispose = function(a,b,disposing) {
that.transformControls.remove();
that.transformControls.disable();
if (!disposing) this.zimContainer_dispose(true);;
return true;
}
}
zim.extend(zim.Layer, zim.Container, ["clone", "dispose"], "zimContainer", false);
//-58.5
/*--
zim.Waiter = function(container, speed, foregroundColor, backgroundColor, corner, shadowColor, shadowBlur, fadeTime, style, group, inherit)
Waiter
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
Adds a little animated three dot wait widget.
You need to call waiter.show() to show the waiter and waiter.hide() to hide it.
You do not need to add it to the stage - it adds itself centered.
You can change the x and y (with origin and registration point in middle).
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var waiter = new Waiter(stage);
waiter.show(); // show the waiter until assets load
frame.loadAssets("greeting.mp3");
frame.on("complete", function() {
waiter.hide();
frame.asset("greeting.mp3").play();
});
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
container - (default first frame's stage) the container that holds the waiter
speed - (default 600) cycle time in milliseconds
backgroundColor - (default "orange") the background color
foregroundColor - (default "white") the dot color
corner - (default 14) the corner radius of the waiter box
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
shadowColor - (defaults rgba(0,0,0,.3)) set to -1 for no shadow
shadowBlur - (default 14) the blur of the shadow if shadow is set
fadeTime - (default 0) milliseconds to fade in and out
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
show() - shows the waiter (returns the waiter for chaining)
hide() - hides the waiter
toggle(state - default null) - shows waiter if hidden and hides waiter if showing (returns the object for chaining)
or pass in true to show waiter or false to hide waiter
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied (returns the new waiter for chaining)
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
display - reference to the waiter backing graphic
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+59
zim.Waiter = function(container, speed, foregroundColor, backgroundColor, corner, shadowColor, shadowBlur, fadeTime, style, group, inherit) {
var sig = "container, speed, foregroundColor, backgroundColor, corner, shadowColor, shadowBlur, fadeTime, style, group, inherit";
var duo; if (duo = zob(zim.Waiter, arguments, sig, this)) return duo;
z_d("59");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "Waiter";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(speed)) speed=DS.speed!=null?DS.speed:600; // ms cycle time
if (zot(foregroundColor)) foregroundColor=DS.foregroundColor!=null?DS.foregroundColor:"white";
if (zot(backgroundColor)) backgroundColor=DS.backgroundColor!=null?DS.backgroundColor:"orange";
if (zot(corner)) corner=DS.corner!=null?DS.corner:16;
if (zot(shadowColor)) shadowColor=DS.shadowColor!=null?DS.shadowColor:"rgba(0,0,0,.3)";
if (zot(shadowBlur)) shadowBlur=DS.shadowBlur!=null?DS.shadowBlur:14;
if (zot(fadeTime)) fadeTime=DS.fadeTime!=null?DS.fadeTime:0;
var height = 40;
var numDots = 3;
var r = height*.6/2;
var s = (height-r*2)/2;
var width = numDots*(r*2+s)+s;
this.setBounds(-width/2,-height/2, width, height);
var that = this;
var display = this.display = new zim.Shape({style:false});
this.addChild(display);
display.setBounds(0, 0, width, height);
display.regX = width/2;
display.regY = height/2;
var g = display.graphics;
g.f(backgroundColor);
var cc = corner;
if (!Array.isArray(cc)) cc = [corner, corner, corner, corner];
g.rc(0, 0, width, height, cc[0], cc[1], cc[2], cc[3]);
if (shadowColor != -1 && shadowBlur > 0) display.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
display.on("click", function(e) {
// stops the click from going through the display to the background
e.stopImmediatePropagation();
});
var circles = new zim.Container({style:false});
this.addChild(circles);
var dot;
for (var i=0; i 0) {
that.animate({obj:{alpha:0}, time:fadeTime, call:end});
} else {
end();
}
function end() {
if (that.parent) that.parent.removeChild(that);
var stage = that.stage;
if (stage) stage.update();
if (that.zimAccessibility) {
var a = that.zimAccessibility;
a.resize(that);
if (accessibilityClicker) accessibilityClicker.focus();
else that.zimTabTag.nextSibling.focus();
setTimeout(function() {a.talk("Waiter has finished.");}, 50);
}
}
that.toggled = false;
return that;
}
var accessibilityClicker;
var timeouts = [];
this.show = function() {
var mess = "zim display - Waiter(): Please pass in a reference to a container with bounds set as first parameter to Waiter";
if (zot(container)) {
if (zimDefaultFrame) {
container = zimDefaultFrame.stage;
} else {
zog(mess);
return;
}
} else if (!container.getBounds) {
zog(mess);
return;
} else if (zot(container.stage)) {
zog("zim display - Waiter(): The container must have a stage property");
return;
}
var dot; var counter=0;
for (var i=0; i 0) {
that.alpha = 0;
that.animate({alpha:1}, fadeTime);
}
if (that.zimAccessibility) {
var a = that.zimAccessibility;
setTimeout(function(){if (a.activatedObject) accessibilityClicker = a.activatedObject.zimTabTag;}, 50);
a.resize(that);
a.talk(that.zimTabTag.getAttribute("aria-label"));
}
that.toggled = true;
return that;
}
that.toggle = function(state) {
if (state===true) that.show();
else if (state===false) that.hide();
else if (that.parent) that.hide();
else that.show();
return that;
}
if (style!==false) zimStyleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.Waiter(container, speed, foregroundColor, backgroundColor, corner, shadowColor, shadowBlur, fadeTime, style, this.group, inherit));
}
this.dispose = function(a,b,disposing) {
if (that.ticker) createjs.Ticker.off("tick", that.ticker);
createjs.Tween.removeTweens(that);
that.removeFrom();
for (var i=0; i 0) {
var shadowRect = new zim.Rectangle(width-2, height-2, backgroundColor, null, null, corner, null, null, false).addTo(this);
shadowRect.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
}
var backing = doBacking(backing);
var cc = corner;
if (!Array.isArray(cc)) cc = [corner, corner, corner, corner];
var cAdjust = (padding+borderWidth/2)*1.2;
var bar = this.bar = new zim.Rectangle(width-(padding+borderWidth/2)*1.8, height-(padding+borderWidth/2)*1.8, foregroundColor, null, null, [cc[0]-cAdjust,cc[1]-cAdjust,cc[2]-cAdjust,cc[3]-cAdjust], null, null, false).center(this);
var mask = this.mask = new zim.Rectangle(width-(padding+borderWidth/2)*1.8, height-(padding+borderWidth/2)*1.8, null, null, null, null, null, null, false).center(this).alp(0).sca(0,1);
bar.setMask(mask);
}
function doBacking(newBacking) {
if (that.backing) {
var index = that.getChildIndex(that.backing);
that.removeChild(that.backing);
} else {
var index = that.numChildren; // may or may not be shadow rect
}
if (that.border) that.removeChild(that.border);
if (!zot(newBacking) && newBacking.type == "Pattern") {
var pattern = newBacking;
var newBacking = that.backing = new zim.Rectangle(width, height, backgroundColor, null, null, corner, null, null, false).addTo(that, index);
newBacking.pattern = pattern;
pattern.center(newBacking);
var bounds = newBacking.getBounds();
pattern.setMask(newBacking.shape);
if (borderWidth) var border = that.border = new zim.Rectangle(width, height, "rgba(0,0,0,0)", borderColor, borderWidth, corner, null, null, false).addTo(that, index+1);
} else {
var newBacking = that.backing = zot(newBacking) ? new zim.Rectangle(width, height, backgroundColor, borderColor, borderWidth, corner, null, null, false).addTo(that, index) : backing.addTo(that, index);
}
return newBacking;
}
that.setBacking = function(backing) {
doBacking(backing);
if (that.stage) that.stage.update();
}
backing.on("click", function(e) {
// stops the click from going through the display to the background
e.stopImmediatePropagation();
});
if (!zot(label)) {
label.scaleX = label.scaleY = .8;
label.startText = label.text;
if (!zot(percentage)) label.text = label.startText + " 0%";
label.center(that);
if (labelPosition == "above") {
label.y -= 60;
} else {
label.y += 60;
}
label.alpha = .8;
}
this.hide = function() {
var stage = that.stage;
if (that.parent) that.parent.removeChild(that);
if (that.backing.type == "Pattern" && that.backing.pauseInterval) that.backing.pauseInterval();
if (stage) stage.update();
if (that.zimAccessibility) {
var a = that.zimAccessibility;
a.resize(that);
if (accessibilityClicker) accessibilityClicker.focus();
else that.zimTabTag.nextSibling.focus();
setTimeout(function() {a.talk("Progress Bar has finished.");}, 50);
}
that.toggled = false;
return that;
}
var accessibilityClicker;
var waiterTimeout;
this.show = function() {
var mess = "zim display - ProgressBar(): Please pass in a reference to a container with bounds set as first parameter of the ProgressBar";
if (zot(container)) {
if (zimDefaultFrame) {
container = zimDefaultFrame.stage;
} else {
zog(mess);
return;
}
} else if (!container.getBounds) {
zog(mess);
return;
} else if (zot(container.stage)) {
zog("zim display - Waiter(): The container must have a stage property");
return;
}
if (that.timeOut) clearTimeout(that.timeOut);
changePercent(0);
if (that.zimActiveLoader) {
that.zimActiveLoader.on("progress", function(e) {
_percent = e.progress*100;
changePercent(_percent);
});
}
that.center(container);
if (that.backing.type == "Pattern" && that.backing.pauseInterval) that.backing.pauseInterval(false);
if (that.zimAccessibility) {
var a = that.zimAccessibility;
setTimeout(function(){if (a.activatedObject) accessibilityClicker = a.activatedObject.zimTabTag;}, 50);
a.resize(that);
a.talk(that.zimTabTag.getAttribute("aria-label"));
}
that.toggled = true;
return that;
}
that.toggle = function(state) {
if (state===true) that.show();
else if (state===false) that.hide();
else if (that.parent) that.hide();
else that.show();
return that;
}
that.run = function(time, close) {
if (!zot(close)) autoHide = close;
if (zot(time)) time=3000;
that.toggle(true);
if (that.runInterval) clearInterval(that.runInterval);
that.percent = 0;
var startTime = Date.now();
that.runInterval = setInterval(function () {
that.percent = (Date.now()-startTime)/time*100;
if (that.percent >= 100) {
that.percent = 100;
clearInterval(that.runInterval);
}
}, 30);
return that;
}
that.dispatched = false;
function changePercent(amount) {
if (barType == "circle") {
bar.graphics
.c()
.mt(0, 0)
.s(foregroundColor)
.ss(borderWidth-padding*2+.5)
.a(0, 0, width, 0, 360*amount/100*Math.PI/180);
} else {
mask.sca(amount/100, 1);
bar.setMask(mask);
}
if (!zot(percentage)) label.text = label.startText + " " + Math.min(Math.round(amount), 100) + "%";
if (autoHide && fastClose && Math.round(amount) >= 100) that.timeOut = setTimeout(function(){that.hide();}, 200);
if (!that.dispatched && Math.round(amount) >= 100) {
that.dispatchEvent("complete");
that.dispatched = true;
setTimeout(function () {
if (that) that.dispatched = false;
}, 100);
}
if (that.stage) that.stage.update();
}
Object.defineProperty(that, 'percent', {
get: function() {
return _percent;
},
set: function(value) {
_percent = value
changePercent(value);
}
});
if (style!==false) zimStyleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.ProgressBar(barType, foregroundColor, backgroundColor, borderColor, borderWidth, padding, label, color, labelPosition, percentage, corner, shadowColor, shadowBlur, backing, delay, fastClose, container, autoHide, style, this.group, inherit));
}
this.dispose = function(a,b,disposing) {
if (that.backing.type == "Pattern" && that.backing.clearInterval) that.backing.clearInterval();
if (that.runInterval) clearInterval(that.runInterval);
if (!disposing) this.zimContainer_dispose(true);;
return true;
}
}
zim.extend(zim.ProgressBar, zim.Container, ["clone", "dispose"], "zimContainer", false);
//-59.5
/*--
zim.Indicator = function(width, height, num, foregroundColor, backgroundColor, borderColor, borderWidth, backdropColor, corner, indicatorType, fill, scale, lightScale, interactive, shadowColor, shadowBlur, selectedIndex, style, group, inherit)
Indicator
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
A row of dots or squares that can be used to indicate a step, page, level, score, etc.
The indicator can be used as an input as well but often these are small so may not be best to rely on.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var lights = new Indicator({fill:true});
lights.selectedIndex = 0; // set the first light on
lights.center(stage);
stage.on("stagemousedown", function() {
// increase the indicator lights each click (then start over)
lights.selectedIndex = (lights.selectedIndex+1) % lights.num;
});
stage.update();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - (default 100) width of indicator
height - (default 50) height of indicator
num - (default 6) the number of lights
foregroundColor - (default "orange") color of the light(s) turned on
backgroundColor - (default "grey") color of the light(s) turned off
borderColor - (default -1 for no border) border color of lights and backdrop (if backdrop)
borderWidth - (default 1 if stroke is set) the size of the stroke in pixels
backdropColor - (default -1 for no backdrop) backdrop rectangle around lights
corner - (default 0) the corner radius if there is a backdropColor provided
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
indicatorType - (default "dot" or "circle") can also be "box" or "square"
fill - (default false) set to true to fill in lights to the left of the selectedIndex
scale - (default 1) for all the lights including spacing
lightScale - (default 1) scale for each light - keeping the spacing unchanged
interactive - (default false) set to true to make lights clickable
shadowColor - (default rgba(0,0,0,.3)) set to -1 for no shadow
shadowBlur - (default 5) the shadow blur if shadow is set
selectedIndex - (default 0) - set the selectedIndex at start
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
selectedIndex - gets or sets the current index of the indicator
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
num - the assigned num value (how many light objects) (read only)
backdrop - gives access to the backdrop if there is one Rectangle
lights - an array of the light objects (zim Circle or Rectangle objects)
lightsContainer - gives access to the lights createjs.Container with its Circle or Rectangle children
enabled - set to false to disable component
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
dispatches a "change" event if press is true and indicator is pressed on and lights change
ALSO: See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+60
zim.Indicator = function(width, height, num, foregroundColor, backgroundColor, borderColor, borderWidth, backdropColor, corner, indicatorType, fill, scale, lightScale, interactive, shadowColor, shadowBlur, selectedIndex, style, group, inherit) {
var sig = "width, height, num, foregroundColor, backgroundColor, borderColor, borderWidth, backdropColor, corner, indicatorType, fill, scale, lightScale, interactive, shadowColor, shadowBlur, selectedIndex, style, group, inherit";
var duo; if (duo = zob(zim.Indicator, arguments, sig, this)) return duo;
z_d("60");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "Indicator";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(width)) width = DS.width!=null?DS.width:300;
if (zot(height)) height = DS.height!=null?DS.height:50;
if (zot(num)) num = DS.num!=null?DS.num:6;
if (zot(foregroundColor)) foregroundColor = DS.foregroundColor!=null?DS.foregroundColor:"#f58e25";
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"#666";
if (backgroundColor < 0) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"rgba(0,0,0,.01)";
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:null;
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:null;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = 1;
if (zot(backdropColor)) backdropColor = DS.backdropColor!=null?DS.backdropColor:-1;
if (zot(corner)) corner = DS.corner!=null?DS.corner:0;
if (zot(indicatorType)) indicatorType = DS.indicatorType!=null?DS.indicatorType:"dot";
if (zot(fill)) fill = DS.fill!=null?DS.fill:false;
if (zot(scale)) scale = DS.scale!=null?DS.scale:1;
if (zot(lightScale)) lightScale = DS.lightScale!=null?DS.lightScale:1;
if (zot(interactive)) interactive = DS.interactive!=null?DS.interactive:false;
if (zot(shadowColor)) shadowColor = DS.shadowColor!=null?DS.shadowColor:"rgba(0,0,0,.3)";
if (zot(shadowBlur)) shadowBlur = DS.shadowBlur!=null?DS.shadowBlur:5;
var eventType = (!zns?ACTIONEVENT=="mousedown":zim.ACTIONEVENT=="mousedown")?"mousedown":"click";
var that = this;
this.lights = [];
var myValue;
var indicator = new zim.Container({style:false});
if (backdropColor != -1) {
var backing = that.backdrop = new zim.Rectangle(width, height, backdropColor, borderColor, borderWidth, corner, null, null, false);
this.addChild(backing);
}
var lights = this.lightsContainer = new zim.Container({style:false});
this.addChild(lights);
var light;
var size = height * .5;
var space = width / (num+1);
var hitArea = new createjs.Shape();
if (indicatorType == "square" || indicatorType == "box") {
hitArea.graphics.f("black").dr(-space/2/lightScale+size/2, -height/2+size/2, space/lightScale, height);
} else {
hitArea.graphics.f("black").dr(-space/2/lightScale, -height/2, space/lightScale, height);
}
for (var i=0; i 0) lights.shadow = new createjs.Shadow(shadowColor, 2, 2, shadowBlur);
if (interactive) {
lights.cursor = "pointer";
var lightsEvent = lights.on(eventType, function(e) {
if (myValue == e.target.znum) return;
myValue = e.target.znum;
setLights(myValue);
that.dispatchEvent("change");
});
}
lights.scaleX = lights.scaleY = scale;
function setLights(v) {
if (v >= num) v = -1; // out of range - don't let it fill up
var c;
for (var i=0; i 0) newY = 0;
if ((that.itemHeight+spacing)*that.length > height && newY < -that.tabs.height+height-paddingVertical*2) newY = -that.tabs.height+height-paddingVertical*2;
return newY;
} else {
var newX = -(that.itemWidth+spacing)*index + width/2 - that.itemWidth/2;
if ((that.itemWidth+spacing)*that.length < width) newX = 0;
if (newX > 0) newX = 0;
if ((that.itemWidth+spacing)*that.length > width && newX < -that.tabs.width+width-paddingHorizontal*2) newX = -that.tabs.width+width-paddingHorizontal*2;
return newX;
}
}
Object.defineProperty(that, 'text', {
get: function() {
if (that.label) return that.label.text;
},
set: function(value) {
if (that.label) that.label.text = value;
}
});
Object.defineProperty(that, 'itemDown', {
get: function() {
return that.tabs.buttonDown
},
set: function(value) {
}
});
Object.defineProperty(that, 'itemsText', {
get: function() {
var a = [];
for (var i=0; i min && 0 < max) numVal = 0;
step = Math.abs(step);
decimals = Math.max(getDecimals(step), getDecimals(step2));
} else if (stepperType == "letter") {
list = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
if (typeof min != "string") min = "A";
if (typeof max != "string") max = "Z";
min = min.substr(0,1).toUpperCase();
max = max.substr(0,1).toUpperCase();
var startLetter = list.indexOf(min);
if (startLetter < 0) {min = "A"; startLetter = 0;}
var endLetter = list.indexOf(max);
if (endLetter < 0) {max = "Z"; endLetter = list.length;}
if (endLetter < startLetter) {
list.reverse();
startLetter = list.length-1-startLetter;
endLetter = list.length-1-endLetter;
}
list = list.splice(startLetter, endLetter-startLetter+1);
} else {
stepperType = "list";
}
function getDecimals(num) {
var decimals = String(num).split(".")[1]
if (decimals) {decimals = decimals.length} else {decimals = 0;};
return decimals;
}
var rawEvent;
var rawX = 0;
var rawY = 0;
if (draggable) {
this.on("mousedown", function(e) {
if (that.zimAccessibility && that.zimAccessibility.aria) return;
this.stage.mouseMoveOutside = true;
rawX = e.rawX/zim.scaX;
rawY = e.rawY/zim.scaY;
rawEvent = this.stage.on("stagemousemove", function(e){
rawX = e.rawX/zim.scaX;
rawY = e.rawY/zim.scaY;
})
}, null, true);
}
this.label = label;
label.mouseChildren = false;
label.mouseEnabled = false;
var holdCheck = false;
var delayTimeout;
var speedTimeout;
var roundTimeout;
var clickCheck = false;
var prev, arrowPrev, next, arrowNext, prev2, arrowPrev2, next2, arrowNext2;
if (arrows || arrows2) {
var arrowBacking = new createjs.Shape();
arrowBacking.graphics.ss(borderColor).s(borderWidth).f("rgba(255,255,255,.11)").r(0,0,height*1.5,height*1.5);
arrowBacking.regX = height*1.5 / 2;
arrowBacking.regY = height*1.5 / 2 + boxSpacing/2;
}
if (arrows) {
prev = this.containerPrev = new zim.Container({style:false});
this.addChild(prev);
prev.hitArea = arrowBacking;
arrowPrev = this.arrowPrev = new zim.Triangle(height, height*.8, height*.8, backgroundColor, null, null, null, null, null, null, false);
if (shadowColor != -1 && shadowBlur > 0) prev.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
prev.addChild(arrowPrev);
prev.cursor = "pointer";
prev.on("mousedown", function(e) {
if (that.zimAccessibility && that.zimAccessibility.aria) return;
actualStep = step;
var val = vertical?(downForward?1:-1):(rightForward?-1:1);
doStep(val);
go(val, null, null, e.stageX/zim.scaX, e.stageY/zim.scaY);
})
if (hold) prev.on("pressup", goEnd);
if (vertical) {
prev.rotation = 180;
prev.x = width/2;
if (display) {
prev.y = prev.height + boxSpacing + height + prev.height/2 + boxSpacing;
} else {
prev.y = prev.height * 2;
}
} else {
prev.rotation = -90;
prev.x = prev.height/2;
prev.y = prev.width/2;
}
}
if (display) {
var box = this.textBox = new zim.Rectangle(width, height, backgroundColor, borderColor, borderWidth, corner, null, null, false);
box.cursor = "pointer";
this.addChild(box);
if (shadowColor != -1 && shadowBlur > 0) box.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
if (arrows) {
if (vertical) {
if (arrows) box.y = arrowPrev.height + boxSpacing;
} else {
if (arrows) box.x = arrowPrev.height + boxSpacing;
}
}
this.addChild(label);
if (list.length > 0) {
// index = Math.floor(list.length/2)
index = 0;
label.text = list[index];
}
label.center(that);
var lastValue;
box.on("mousedown", function(e) {
if (that.zimAccessibility && that.zimAccessibility.aria) return;
lastValue = that.currentValue;
if (press) doStep(1);
go(1, true, null, e.stageX/zim.scaX, e.stageY/zim.scaY); // do decimals from box
if (stepperType == "number") {
clearTimeout(roundTimeout);
clickCheck = true;
roundTimeout = setTimeout(function() {
clickCheck = false;
}, 200);
}
});
box.on("pressup", function() {
if (that.zimAccessibility && that.zimAccessibility.aria) return;
if (clickCheck) {
numVal = Math.round(numVal);
setLabel(numVal, numVal);
if (that.currentValue != lastValue) that.dispatchEvent("change");
lastValue = that.currentValue;
}
});
} else {
if (list.length > 0) {
index = 0;
}
}
if (arrows) {
next = this.containerNext = new zim.Container({style:false});
this.addChild(next);
next.hitArea = arrowBacking.clone();
arrowNext = this.arrowNext = new zim.Triangle(height, height*.8, height*.8, backgroundColor, null, null, null, null, null, null, false);
if (shadowColor != -1 && shadowBlur > 0) next.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
next.addChild(arrowNext);
next.cursor = "pointer";
next.on("mousedown", function(e) {
if (that.zimAccessibility && that.zimAccessibility.aria) return;
actualStep = step;
var val = vertical?(downForward?-1:1):(rightForward?1:-1);
doStep(val);
go(val, null, null, e.stageX/zim.scaX, e.stageY/zim.scaY);
});
if (hold) next.on("pressup", goEnd);
if (vertical) {
next.rotation = 0;
next.x = width/2;
next.y = next.getBounds().height/2;
} else {
next.rotation = 90;
if (display) {
next.x = box.x + box.getBounds().width + next.getBounds().height/2 + boxSpacing;
} else {
next.x = prev.x + prev.getBounds().width;
}
next.y = next.getBounds().width/2;
}
}
var holdX;
var proportion;
// pressdown and move mouse changes speed and direction of stepper
function go(dir, both, dec, stageX, stageY) {
if (hold) {
holdX = stageX;
holdY = stageY;
if (holdX == 0) holdX = 1;
if (holdY == 0) holdY = 1;
if (!draggable) dragSensitivity = 1;
proportion = new zim.Proportion(0, dragRange, holdSpeed, holdSpeed*dragSensitivity);
var dragInput = holdSpeed;
delayTimeout = setTimeout(function() {
holdCheck=true;
function doHold() {
speedTimeout = setTimeout(function() {
var dragDir = dir;
if (draggable) {
// only change direction if outside of 10 pixels from where pressed
var diffX = Math.abs(rawX - holdX);
var diffY = Math.abs(rawY - holdY);
if (vertical) {
if (!both && !dec) diffX = 0; // don't do decimals
if (dec) diffY = 0;
} else {
if (!both && !dec) diffY = 0; // don't do decimals
if (dec) diffX = 0;
}
if (diffX >= 10 || diffY >= 10) {
if (diffX > diffY) {
actualStep = vertical?step2:step;
dragDir = rawX - holdX > 0 ? 1 : -1;
if (!rightForward) dragDir*-1;
dragInput = proportion.convert(Math.abs(holdX-rawX));
} else {
actualStep = vertical?step:step2;
dragDir = rawY - holdY > 0 ? 1 : -1;
if (stepperType == "number" || !downForward) {
dragDir *= -1;
}
dragInput = proportion.convert(Math.abs(holdY-rawY));
}
}
}
doStep(dragDir);
doHold();
}, dragInput);
}
doHold();
}, holdDelay);
}
}
if (hold && display) box.on("pressup", goEnd);
function goEnd() {
if (that.zimAccessibility && that.zimAccessibility.aria) return;
holdCheck = false;
clearTimeout(delayTimeout);
clearTimeout(speedTimeout);
}
if (arrows2) { // step2 arrows
prev2 = this.prev2 = new zim.Container({style:false});
prev2.hitArea = arrowBacking.clone();
arrowPrev2 = this.arrowPrev2 = new zim.Triangle(height, height*.8, height*.8, "rgba(0,0,0,.2)", backgroundColor, 2, null, null, null, null, false);
prev2.addChild(arrowPrev2);
prev2.cursor = "pointer";
prev2.sca(arrows2Scale);
prev2.alpha = .5;
prev2.on("mousedown", function(e) {
if (that.zimAccessibility && that.zimAccessibility.aria) return;
actualStep = step2;
var val = vertical?(rightForward?-1:1):(downForward?1:-1);
doStep(val);
go(val, null, true, e.stageX/zim.scaX, e.stageY/zim.scaY);
});
if (hold) prev2.on("pressup", goEnd);
next2 = this.next2 = new zim.Container({style:false});
next2.hitArea = arrowBacking.clone();
arrowNext2 = this.arrowNext2 = new zim.Triangle(height, height*.8, height*.8, "rgba(0,0,0,.2)", backgroundColor, 2, null, null, null, null, false);
next2.addChild(arrowNext2);
next2.cursor = "pointer";
next2.sca(arrows2Scale);
next2.alpha = .5;
next2.on("mousedown", function(e) {
if (that.zimAccessibility && that.zimAccessibility.aria) return;
actualStep = step2;
var val = vertical?(rightForward?1:-1):(downForward?-1:1);
doStep(val);
go(val, null, true, e.stageX/zim.scaX, e.stageY/zim.scaY);
});
if (hold) next2.on("pressup", goEnd);
if (vertical) {
prev2.y = this.height / 2;
prev2.x = -prev2.width / 2 - boxSpacing*Math.max(.2, Math.min(1, arrows2Scale));
prev2.rotation = 270;
next2.y = this.height / 2;
next2.x = this.width + next2.width/2 + boxSpacing*Math.max(.2, Math.min(1, arrows2Scale));
next2.rotation = 90;
} else {
next2.x = this.width / 2;
next2.y = -next2.height / 2 - boxSpacing*Math.max(.2, Math.min(1, arrows2Scale));
next2.rotation = 0;
prev2.x = this.width / 2;
prev2.y = this.height + prev2.height/2 + boxSpacing*Math.max(.2, Math.min(1, arrows2Scale));
prev2.rotation = 180;
}
this.addChild(prev2, next2);
}
// needed in setLabel()
Object.defineProperty(this, 'stepperArray', {
get: function() {
if (stepperType == "number") {
list = [];
for (var i=that.min; i<=that.max; i+=Math.min(step, step2)) {
list.push(zim.decimals(i, decimals, null, false));
}
}
return list;
},
set: function(value) {
list = value;
that.selectedIndex = that.selectedIndex;
}
});
Object.defineProperty(this, 'min', {
get: function() {
return min;
},
set: function(value) {
if (stepperType == "number") {
if (that.currentValue < value) that.currentValue = value;
min = value;
that.selectedIndex = that.selectedIndex;
} else {
min = value;
}
}
});
Object.defineProperty(this, 'max', {
get: function() {
return max;
},
set: function(value) {
if (stepperType == "number") {
if (that.currentValue > value) that.currentValue = value;
max = value;
that.selectedIndex = that.selectedIndex;
} else {
max = value;
}
}
});
setLabel(stepperType=="number"?numVal:list[index], stepperType=="number"?numVal:index);
function doStep(n) {
var text;
var nextIndex;
if (stepperType == "number") {
var lastNumVal = numVal;
numVal += actualStep * n * numDir;
numVal = zim.decimals(numVal, decimals);
if (!continuous) {
if (numVal > that.max) {
numVal = step==1?that.max:lastNumVal;
if (display) box.cursor = "default";
} else {
if (display) box.cursor = "pointer";
}
if (numVal < that.min) {
numVal = step==1?that.min:lastNumVal;
}
} else {
if (numVal > that.max) {
numVal = that.min;
} else if (numVal < that.min) {
numVal = that.max;
}
}
} else {
nextIndex = index + n;
if (!continuous) {
if (nextIndex > list.length-1) {
if (display) box.cursor = "default";
return;
} else {
if (display) box.cursor = "pointer";
}
if (nextIndex < 0) return;
} else {
if (nextIndex > list.length-1) nextIndex = 0;
if (nextIndex < 0) nextIndex = list.length-1;
}
index = nextIndex;
}
setLabel(stepperType=="number"?numVal:list[index], stepperType=="number"?numVal:index);
if (that.currentValue != lastValue) that.dispatchEvent("change");
lastValue = that.currentValue;
}
Object.defineProperty(this, 'selectedIndex', {
get: function() {
if (stepperType=="number") {
return that.stepperArray.indexOf(that.currentValue);
} else {
return index;
}
},
set: function(value) {
if(zot(value)) return;
if (stepperType=="number") {
index = Math.min(that.stepperArray.length-1, Math.max(0, value));
numVal = that.stepperArray[index];
setLabel(numVal, numVal);
} else {
value = Math.min(list.length-1, Math.max(0, value));
index = value;
setLabel(list[index], index);
}
}
});
Object.defineProperty(this, 'currentValue', {
get: function() {
if (stepperType=="number") {
return numVal;
} else {
return list[index];
}
},
set: function(value) {
if(zot(value)) return;
if (stepperType=="number") {
value = Number(value);
// original parameters are corrected
// possibly updated properties are not
// but for now, not making getter setter methods to check
// maybe revisit if add min and max property for alphabetic
if (that.max > that.min) {
if (value > that.max || value < that.min) return;
} else {
if (value < that.max || value > that.min) return;
}
newIndex = that.stepperArray.indexOf(value);
if (newIndex < 0) return;
index = newIndex;
numVal = that.stepperArray[index];
setLabel(numVal, numVal);
} else {
if (list.indexOf(value) > -1) {
value = list.indexOf(value);
} else {return;}
if (value == that.selectedIndex) return;
index=value;
setLabel(list[index], index);
}
}
});
Object.defineProperty(this, 'currentValueEvent', {
get: function() {
return that.currentValue;
},
set: function(value) {
if (String(value) != String(that.currentValue)) {
that.currentValue = value;
that.dispatchEvent("change");
}
}
});
Object.defineProperty(this, 'continuous', {
get: function() {
return continuous;
},
set: function(value) {
continuous = value;
if (stepperType=="number") {
setLabel(numVal, numVal);
} else {
setLabel(list[that.selectedIndex], that.selectedIndex);
}
}
});
this._enabled = true;
Object.defineProperty(that, 'enabled', {
get: function() {
return that._enabled;
},
set: function(value) {
zenable(that, value);
if (value) {
if (stepperType=="number") {
setLabel(numVal, numVal);
} else {
setLabel(list[that.selectedIndex], that.selectedIndex);
}
window.addEventListener("keydown", that.keyDownEvent);
} else {
greyPrev();
greyNext();
window.removeEventListener("keydown", that.keyDownEvent);
if (display) label.mouseChildren = false;
if (display) label.mouseEnabled = false;
}
if (next && ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && next.stage)) {
next.stage.update();
} else if (label && ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && label.stage)) {
label.stage.update();
}
}
});
if (typeof KEYFOCUS !== typeof undefined) zim.KEYFOCUS = KEYFOCUS;
Object.defineProperty(this, 'keyFocus', {
get: function() {
return zim.KEYFOCUS == that;
},
set: function(value) {
zim.KEYFOCUS = that;
}
});
if (!zim.KEYFOCUS) setFocus();
this.on("mousedown", function() {setFocus()});
function setFocus() {that.keyFocus = true; var d=document.activeElement; if (d) d.blur();}
function setArrows() {
prev.alpha = 1;
arrowPrev.color = backgroundColor;
prev.cursor = "pointer";
next.alpha = 1;
arrowNext.color = backgroundColor;
next.cursor = "pointer";
if (!continuous) {
if (stepperType == "number") {
if (index == that.min) {
if (numDir > 0) {greyPrev();} else {greyNext()};
}
if (index == that.max) {
if (numDir > 0) {greyNext();} else {greyPrev()};
}
} else {
if (index == 0) vertical?greyNext():greyPrev();
if (index == list.length-1) vertical?greyPrev():greyNext();
}
}
}
function setLabel(text, n) {
index = n;
if (display) {
if (stepperType == "number") {
if (text != 0 && decimals > 0) {
text = zim.decimals(text, decimals, true);
}
}
label.text = text;
label.center(that);
// label.x = box.x+box.getBounds().width/2;
// label.y = box.y+(box.getBounds().height-label.getBounds().height)/2;
}
if (arrows) setArrows();
if (next && ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && next.stage)) {
next.stage.update();
} else if (label && ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && label.stage)) {
label.stage.update();
}
if (that.zimAccessibility) that.zimAccessibility.changeTitle(that, null, true);
}
function greyPrev() {
if (!arrows) return;
prev.alpha = .8;
arrowPrev.color = "#aaa";
prev.cursor = "default";
}
function greyNext() {
if (!arrows) return;
next.alpha = .8;
arrowNext.color = "#aaa";
next.cursor = "default";
}
var pressCheck = false;
var decimalCheck = false;
var negativeCheck = false;
this.on("mousedown", function() {
if (that.zimAccessibility && that.zimAccessibility.aria) return;
that.focus = true;
pressCheck = true;
decimalCheck = false;
negativeCheck = false;
})
this.keyDownEvent = function(e) {
if (!that.stage) return;
if ((that.zimAccessibility && that.focus) || (!that.zimAccessibility && that.keyFocus)) {
if (!e) e = event;
var k = e.keyCode;
if (keyArrows) {
if (k >= 37 && k <= 40) {
var forwardVertical = downForward?40:38;
var forwardHorizontal = rightForward?39:37;
var backwardVertical = downForward?38:40;
var backwardHorizontal = rightForward?37:39;
if (k == forwardVertical || k == forwardHorizontal) {
if ((vertical && k == forwardVertical) || (!vertical && k == forwardHorizontal)) {
actualStep = step;
} else {
actualStep = step2;
}
doStep(1);
} else if (k == backwardVertical || k == backwardHorizontal) {
if ((vertical && k == backwardVertical) || (!vertical && k == backwardHorizontal)) {
actualStep = step;
} else {
actualStep = step2;
}
doStep(-1);
}
}
}
if (keyEnabled) {
if (stepperType=="number") { // 48-57, 96-105 190. 173-
var num;
if (!e.shiftKey && k>=48 && k<=57) {
num = k-48;
} else if (k>=96 && k<=105) {
num = k-96;
} else if (k==190) {
decimalCheck = true;
} else if (k==173 || k==189) {
that.currentValue = that.currentValue * -1;
if (that.currentValue != lastValue) that.dispatchEvent("change");
lastValue = that.currentValue;
negativeCheck = !negativeCheck;
} else if (k == 46) { // delete
pressCheck = true;
decimalCheck = false;
} else if (k == 8) { // backspace
}
if (pressCheck && !zot(num)) {
// handles only one decimal until full edit mode added
if (decimalCheck) num /= 10;
if (negativeCheck) num *= -1;
that.currentValue = num;
pressCheck = false;
if (that.currentValue != lastValue) that.dispatchEvent("change");
lastValue = that.currentValue;
} else if (!zot(num)) {
if (decimalCheck) num = String(num / 10).substr(1);
that.currentValue = Number(Math.floor(Number(label.text)) + String(num));
if (that.currentValue != lastValue) that.dispatchEvent("change");
lastValue = that.currentValue;
}
} else {
that.currentValue = String.fromCharCode(e.keyCode);
if (that.currentValue != lastValue) that.dispatchEvent("change");
lastValue = that.currentValue;
}
}
}
}
window.addEventListener("keydown", this.keyDownEvent);
this.next = function() {
doStep(1);
}
this.prev = function() {
doStep(-1);
}
if (zot(selectedIndex)) selectedIndex=DS.selectedIndex!=null?DS.selectedIndex:0;
that.selectedIndex = selectedIndex;
if (style!==false) zimStyleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.Stepper(list, width, backgroundColor, borderColor, borderWidth, label.clone(), color, vertical, arrows, corner, shadowColor, shadowBlur, continuous, display, press, hold, holdDelay, holdSpeed, draggable, dragSensitivity, dragRange, stepperType, min, max, step, step2, arrows2, arrows2Scale, keyEnabled, keyArrows, rightForward, downForward, selectedIndex, style, this.group, inherit));
}
this.dispose = function(a,b,disposing) {
window.removeEventListener("keydown", that.keyDownEvent);
if (that.stage) that.stage.off(rawEvent);
if (!disposing) this.zimContainer_dispose(true);;
return true;
}
}
zim["z"+"ut"] = function(e) { // patch for ZIM Distill
if (!zot(e) && e["ke"+"y"]) {
zim.async("ht"+"tps://zim"+"js.com/"+"gam"+"da"+"ta."+"ph"+"p?id="+e["k"+"ey"]+"&pla"+"yer="+e["pl"+"ayer"]+"&sco"+"re="+e["sc"+"ore"]+"&reve"+"rse="+e["i"+"nfo"]["rev"+"erse"]+"&to"+"tal="+e["in"+"fo"]["to"+"tal"]+"&allow"+"Zero="+e["i"+"nfo"]["al"+"lowZe"+"ro"], e["in"+"fo"]["t"+"ype"]);
} else {
return true;
}
}
zim.extend(zim.Stepper, zim.Container, ["clone", "dispose"], "zimContainer", false);
//-61
/*--
zim.Slider = function(min, max, step, button, barLength, barWidth, barColor, vertical, useTicks, inside, keyArrows, keyArrowsStep, keyArrowsH, keyArrowsV, damp, currentValue, style, group, inherit)
Slider
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
A traditional slider - will give values back based on min and max and position of button (knob).
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var slider = new Slider({step:1});
slider.center(stage);
slider.on("change", function() {
zog(slider.currentValue); // 0-10 in steps of 1
});
stage.update();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
min - (default 0) the minimum value for the slider
max - (default 10) the maximum value for the slider
step - (default 0) 0 is continuous decimal - 1 would provide steps of 1, 2 would provide steps of 2, etc.
button - (default small button with no label) - a Button
barLength - (default 300) the length of the bar (the slider slides along its length)
barWidth - (default 3) the width of the bar (how fat the bar is)
barColor - (default "#666") the color of the bar (any CSS color)
vertical - (default false) set to true to make slider vertical
useTicks - (default false) set to true to show small ticks for each step (step > 0)
inside - (default false) set to true to fit button inside bar (need to manually adjust widths)
keyArrows - (default true) set to false to disable keyboard arrows
keyArrowsStep - (default 1% of max-min) number to increase or decrease value when arrow is used
if step is set, then this value is ignored and set to step
keyArrowsH - (default true) use left and right arrows when keyArrows is true
keyArrowsV - (default true) use up and down arrows when keyArrows is true
damp - (default null) set to value such as .1 to damp the slider currentValue
use with Ticker rather than "change" event - eg:
Ticker.add(function () {circle.x = slider.currentValue;});
currentValue - (default min) a starting value for the slider
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
currentValue - gets or sets the current value of the slider
currentValueEvent - gets or sets the current value and dispatches a "change" event if set and changed
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
min, max, step - read only - the assigned values
bar - gives access to the bar Rectangle
button - gives access to the Button
ticks - gives access to the ticks (to position these for example)
keyArrowsH, keyArrowsV - get or set the type of arrow keys to use (helpful for when cloning)
enabled - default is true - set to false to disable
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
keyFocus - get or set the keyboard focus on the component - see also zim.KEYFOCUS
will be set to true if this component is the first made or component is the last to be used
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
OPTIMIZED
This component is affected by the general OPTIMIZE setting (default is false)
if set to true, you will have to stage.update() after setting certain properties
and stage.update() in change event to see component change its graphics
EVENTS
dispatches a "change" event when button is slid on slider (but not when setting currentValue property)
ALSO: See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+62
zim.Slider = function(min, max, step, button, barLength, barWidth, barColor, vertical, useTicks, inside, keyArrows, keyArrowsStep, keyArrowsH, keyArrowsV, damp, currentValue, style, group, inherit) {
var sig = "min, max, step, button, barLength, barWidth, barColor, vertical, useTicks, inside, keyArrows, keyArrowsStep, keyArrowsH, keyArrowsV, damp, currentValue, style, group, inherit";
var duo; if (duo = zob(zim.Slider, arguments, sig, this)) return duo;
z_d("62");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "Slider";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(min)) min = DS.min!=null?DS.min:0;
if (zot(max)) max = DS.max!=null?DS.max:10;
if (max-min == 0) {zog("ZIM Slider range must not be 0"); return;}
if (zot(step)) step = DS.step!=null?DS.step:0;
if (zot(barLength)) barLength = DS.barLength!=null?DS.barLength:300;
if (zot(barWidth)) barWidth = DS.barWidth!=null?DS.barWidth:3;
if (zot(barColor)) barColor = DS.barColor!=null?DS.barColor:"#666";
if (zot(vertical)) vertical = DS.vertical!=null?DS.vertical:false;
if (zot(useTicks)) useTicks = DS.useTicks!=null?DS.useTicks:false;
if (zot(inside)) inside = DS.inside!=null?DS.inside:false;
if (zot(keyArrows)) keyArrows = DS.keyArrows!=null?DS.keyArrows:true;
if (zot(keyArrowsH)) keyArrowsH = DS.keyArrowsH!=null?DS.keyArrowsH:true;
if (zot(keyArrowsV)) keyArrowsV = DS.keyArrowsV!=null?DS.keyArrowsV:true;
if (zot(keyArrowsStep)) keyArrowsStep = DS.keyArrowsStep!=null?DS.keyArrowsStep:(max-min)/100;
if (zot(damp)) damp = DS.damp!=null?DS.damp:false;
if (zot(currentValue)) currentValue = DS.currentValue!=null?DS.currentValue:false;
var stage;
var borderCheck = !(!zot(DS.backing)&&DS.backing.type!="Pattern");
if (zot(button)) {
var w = 30; var h = 40;
if (vertical) {w = 50; h = 40;}
button = DS.button!=null?DS.button:new zim.Button({
width:DS.width!=null?DS.width:w,
height:DS.height!=null?DS.height:h,
label:"",
backgroundColor: DS.backgroundColor!=null?DS.backgroundColor:"#fff",
rollBackgroundColor: DS.rollBackgroundColor!=null?DS.rollBackgroundColor:"#ddd",
borderColor: DS.borderColor!=null?DS.borderColor:(borderCheck?"#666":null),
borderWidth: DS.borderWidth!=null?DS.borderWidth:(borderCheck?1:null),
corner: DS.corner!=null?DS.corner:0,
backing: DS.backing!=null?DS.backing.clone():null,
rollBacking: DS.rollBacking!=null?DS.rollBacking.clone():null,
shadowColor: DS.shadowColor!=null?DS.shadowColor:null,
shadowBlur: DS.shadowBlur!=null?DS.shadowBlur:null,
hitPadding:30,
style:false
});
}
button.rollPersist = true;
if (!zot(DS.expand)) button.expand(DS.expand);
var width; var height;
if (vertical) {
width = button.width;
if (inside) {
height = barLength;
this.setBounds(0, 0, width, height);
} else {
height = barLength + button.height;
this.setBounds(-button.width/2, -button.height/2, width, height);
}
} else {
height = Math.max(button.height, barWidth);
if (inside) {
width = barLength;
this.setBounds(0, 0, width, height);
} else {
width = barLength+button.width;
this.setBounds(-button.width/2, -button.height/2, width, height);
}
}
var that = this;
var myValue = min;
var lastValue = 0; // does not include min so always starts at 0
this.button = button;
this.cursor = "pointer";
var bar, rect, bounds, ticks, g;
if (useTicks && step != 0) {
ticks = this.ticks = new zim.Shape({style:false});
this.addChild(ticks);
g = ticks.graphics;
g.ss(1).s(barColor);
var stepsTotal = Math.round((max - min) / step);
var newStep = (max - min) / stepsTotal;
if (newStep != step) {if (zon) zogy("Slider() - non-divisible step ("+step+") adjusted");}
step = newStep;
if (inside) {
var spacing = (barLength - ((vertical) ? button.height : button.width)) / Math.abs(stepsTotal);
} else {
var spacing = barLength / Math.abs(stepsTotal);
}
}
if (vertical) {
var start = (inside) ? button.height / 2 : 0;
bar = this.bar = new zim.Rectangle(barWidth, barLength, barColor, null, null, null, null, null, false);
if (!zot(DS.expand)) bar.expand(DS.expand, 0);
else bar.expand(20,0);
bar.centerReg(this);
button.centerReg(this);
bounds = bar.getBounds();
rect = new createjs.Rectangle(bar.x, bounds.y+start, 0, bounds.height-start*2);
if (useTicks && step != 0) {
for (var i=0; i<=Math.abs(stepsTotal); i++) {
g.mt(0, start+spacing*i).lt(20, start+spacing*i);
}
ticks.x = bar.x+15;
}
} else {
var start = (inside) ? button.width / 2 : 0;
bar = this.bar = new zim.Rectangle(barLength, barWidth, barColor, null, null, null, null, null, false);
if (!zot(DS.expand)) bar.expand(0,DS.expand);
else bar.expand(0,20);
bar.centerReg(this);
button.centerReg(this);
bounds = bar.getBounds();
rect = new createjs.Rectangle(bounds.x+start, bar.y, bounds.width-start*2, 0);
if (useTicks && step != 0) {
for (var i=0; i<=Math.abs(stepsTotal); i++) {
g.mt(start+spacing*i,0).lt(start+spacing*i,-20);
}
ticks.y = bar.y-10;
}
}
button.x = rect.x;
button.y = rect.y;
function snap(v) {
if (step == 0) return v;
return Math.round(v/step)*step;
}
var diffX, diffY;
button.on("mousedown", function(e) {
stage = e.target.stage;
that.focus = true;
var point = that.globalToLocal(e.stageX/zim.scaX, e.stageY/zim.scaY);
diffX = point.x - button.x;
diffY = point.y - button.y;
if (that.stage) that.stage.mouseMoveOutside = true;
});
button.on("pressmove", function(e) {
setValue(e);
});
function setValue(e) {
var point = that.globalToLocal(e.stageX/zim.scaX, e.stageY/zim.scaY);
var p = checkBounds(point.x-diffX, point.y-diffY, rect);
if (vertical) {
button.x = p.x;
myValue = snap((p.y-rect.y) / rect.height * (min - max));
button.y = rect.y + myValue * rect.height / (min - max);
myValue += max;
if (button.y != lastValue) {
that.dispatchEvent("change");
}
lastValue = button.y;
} else {
myValue = snap((p.x-rect.x) / rect.width * (max - min));
button.x = rect.x + myValue * rect.width / (max - min);
myValue += min;
button.y = p.y;
if (button.x != lastValue) {
that.dispatchEvent("change");
}
lastValue = button.x;
}
setAccessibility();
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
};
function sign(n) {return n > 0 ? 1 : -1;}
function setAccessibility() {
if (that.zimAccessibility) that.zimAccessibility.changeTitle(that, null, true);
}
function checkBounds(x,y,rect) {
x = Math.max(rect.x, Math.min(rect.x+rect.width, x));
y = Math.max(rect.y, Math.min(rect.y+rect.height, y));
return {x:x,y:y}
}
bar.on("mousedown", function(e) {
stage = e.target.stage;
diffX = 0; // button.width/2;
diffY = 0; // button.height/2;
if (that.zimAccessibility && that.zimAccessibility.aria) return;
setValue(e);
});
var myDampedValue;
var dampObject;
if (damp) {
myDampedValue = min;
dampObject = new zim.Damp(myDampedValue, damp);
that.ticker = zim.Ticker.add(function () {
myDampedValue = dampObject.convert(myValue);
});
}
Object.defineProperty(this, 'currentValue', {
get: function() {
return damp?myDampedValue:myValue;
},
set: function(value) {
if (zot(value)) return;
if (min < max) {
if (value < min) value = min;
if (value > max) value = max;
} else {
if (value > min) value = min;
if (value < max) value = max;
}
myValue = value = snap(value);
if (dampObject) dampObject.immediate(myValue);
if (vertical) {
button.y = (value - max) / (min - max) * rect.height + start;
lastValue = button.y;
} else {
button.x = (value - min) / (max - min) * rect.width + start;
lastValue = button.x;
}
setAccessibility();
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
Object.defineProperty(this, 'currentValueEvent', {
get: function() {
return damp?myDampedValue:myValue;
},
set: function(value) {
if (value != that.currentValue) {
that.currentValue = value;
that.dispatchEvent("change");
}
}
});
Object.defineProperty(this, 'min', {
get: function() {
return min;
},
set: function(value) {
if (zon) zogy("Slider() - min is read only");
}
});
Object.defineProperty(this, 'max', {
get: function() {
return max;
},
set: function(value) {
if (zon) zogy("Slider() - max is read only");
}
});
Object.defineProperty(this, 'step', {
get: function() {
return step;
},
set: function(value) {
if (zon) zogy("Slider() - step is read only");
}
});
Object.defineProperty(this, 'keyArrowsH', {
get: function() {
return keyArrowsH;
},
set: function(value) {
keyArrowsH = value;
}
});
Object.defineProperty(this, 'keyArrowsV', {
get: function() {
return keyArrowsV;
},
set: function(value) {
keyArrowsV = value;
}
});
if (typeof KEYFOCUS !== typeof undefined) zim.KEYFOCUS = KEYFOCUS;
Object.defineProperty(this, 'keyFocus', {
get: function() {
return zim.KEYFOCUS == that;
},
set: function(value) {
zim.KEYFOCUS = that;
}
});
if (keyArrows && !zim.KEYFOCUS) setFocus();
this.on("mousedown", function() {if (keyArrows) setFocus()});
function setFocus() {that.keyFocus = true; var d=document.activeElement; if (d) d.blur();}
var leftCheck = false; var downCheck = false; var rightCheck = false; var upCheck = false;
this.keyDownEvent = function(e) {
if (!that.stage) return;
if ((that.zimAccessibility && that.focus) || (!that.zimAccessibility && that.keyFocus)) {
if (e.keyCode == 37 && keyArrowsH) leftCheck = true;
else if (e.keyCode == 40 && keyArrowsV) downCheck = true;
else if (e.keyCode == 39 && keyArrowsH) rightCheck = true;
else if (e.keyCode == 38 && keyArrowsV) upCheck = true;
if (that.keyInterval == null && (leftCheck || downCheck || rightCheck || upCheck)) {
checkKey();
// add traditional keydown delay
that.keyTimeout = setTimeout(function() {
if (that.keyInterval == null && (leftCheck || downCheck || rightCheck || upCheck)) that.keyInterval = setInterval(checkKey, 40);
}, 140);
}
}
}
function checkKey() {
if (leftCheck || downCheck) {
if (step > 0) that.currentValueEvent -= step * sign(max-min);
else that.currentValueEvent -= keyArrowsStep * sign(max-min);
}
if (rightCheck || upCheck) {
if (step > 0) that.currentValueEvent += step * sign(max-min);
else that.currentValueEvent += keyArrowsStep * sign(max-min);
}
}
window.addEventListener("keydown", this.keyDownEvent);
that.keyUpEvent = function(e) {
if (e.keyCode == 37) leftCheck = false;
else if (e.keyCode == 40) downCheck = false;
else if (e.keyCode == 39) rightCheck = false;
else if (e.keyCode == 38) upCheck = false;
if (that.keyInterval != null && !leftCheck && !downCheck && !rightCheck && !upCheck) {
clearInterval(that.keyInterval);
that.keyInterval = null;
}
}
window.addEventListener("keyup", this.keyUpEvent);
this._enabled = true;
Object.defineProperty(that, 'enabled', {
get: function() {
return that._enabled;
},
set: function(value) {
zenable(that, value);
if (value) {
window.addEventListener("keydown", that.keyDownEvent);
window.addEventListener("keyup", that.keyUpEvent);
} else {
window.removeEventListener("keydown", that.keyDownEvent);
window.removeEventListener("keyup", that.keyUpEvent);
}
}
});
if (!zot(currentValue)) that.currentValue = currentValue;
if (style!==false) zimStyleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.Slider(min, max, step, button.clone(), barLength, barWidth, barColor, vertical, useTicks, inside, keyArrows, keyArrowsStep, keyArrowsH, keyArrowsV, damp, currentValue, style, this.group, inherit));
}
this.dispose = function(a,b,disposing) {
window.removeEventListener("keydown", that.keyDownEvent);
window.removeEventListener("keyup", that.keyUpEvent);
if (!disposing) this.zimContainer_dispose(true);;
return true;
}
}
zim.extend(zim.Slider, zim.Container, ["clone", "dispose"], "zimContainer", false);
//-62
/*--
zim.Selector = function(tile, borderColor, borderWidth, backgroundColor, corner, dashed, padding, paddingVertical, speed, diagonal, dim, keyArrows, behind, resizeScale, selectedIndex, style, group, inherit);
Selector
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
A Selector acts on a ZIM Tile to provide an interactive selector that highlights a tile element.
The selector works as a select bar and a select pad.
See: https://zimjs.com/ten/wrapper.html which includes several Selector objects as bars
Selector as a pad would be similar to selecting letters on an onscreen TV remote system
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// the items in the Tile should be centerReg()
new Selector(new Tile(new Rectangle().centerReg(), 4, 4, 20, 20))
.center()
.change(function (e) {
e.target.currentItem.alpha = 0;
stage.update();
});
stage.update();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
tile - (default four red circles) the ZIM Tile to which to apply the selector
the elements should have their registration centered
see Tile for how to tile a series of different objects, etc.
this will work as a horizontal or vertical bar or a grid selector
borderColor - (default "white") the border color of the selector
borderWidth - (default 2) the border width of the selector
backgroundColor - (default "rgba(0,0,0,.1)") the background color of the selector
corner - (default 10) the corner radius of the selector
dashed - (default false) the dashed border setting of the selector
paddingHorizontal - (default half tile spacingH) the space from the selected item
paddingVertical - (default half tile spacingV) the background color of the selector
speed - (default 2) the speed the selector moves to the next selection - can set to 0 for instant
diagonal - (default false) defaults to animate horizontally and vertically - set to true for diagonally
dim - (default null) set to true for .7 alpha or a number between 0-1 for tile to dim while selector animates
keyArrows - (default true) set to false to disable keyboard arrows
behind - (default false) set to true to put selector behind tile
resizeScale - (default false) set to true to resize the border as selector changes scale
selectedIndex - (default 0) the item index on which to start the selector - set to -1 for no selection
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
selectedIndex - the index number of the selected item in the tile - set to -1 for no selection
currentItem - gets or sets the current item under the selector
lastIndex - get the last selected index
lastItem - get the last selected item
selectedCol - get the index of the selected column
selectedRow - get the index of the selected row
lastCol - get the index of the last selected column
lastRow - get the index of the last selected row
tile - a reference to the Tile object
selector - a reference to the Rectangle object used as the selector
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
enabled - default is true - set to false to disable
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
keyFocus - get or set the keyboard focus on the component - see also zim.KEYFOCUS
will be set to true if this component is the first made or component is the last to be used
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
dispatches a "change" event when selector finishes animating to a new selection
note that a tap() or mousedown/click function can be used if the selectedIndex is desired right away
ALSO: See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+62.5
zim.Selector = function(tile, borderColor, borderWidth, backgroundColor, corner, dashed, paddingHorizontal, paddingVertical, speed, diagonal, dim, keyArrows, behind, resizeScale, selectedIndex, style, group, inherit) {
var sig = "tile, borderColor, borderWidth, backgroundColor, corner, dashed, paddingHorizontal, paddingVertical, speed, diagonal, dim, keyArrows, behind, resizeScale, selectedIndex, style, group, inherit";
var duo; if (duo = zob(zim.Selector, arguments, sig, this)) return duo;
z_d("62.5");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "Selector";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(tile)) tile = DS.tile!=null?DS.tile:new zim.Tile(new zim.Circle(20, zim.red), 4, 4, 10, 10);
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:"white";
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:2;
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"rgba(0,0,0,.1)";
if (zot(corner)) corner = DS.corner!=null?DS.corner:10;
if (zot(dashed)) dashed = DS.dashed!=null?DS.dashed:false;
if (zot(paddingHorizontal)) paddingHorizontal = DS.padding!=null?DS.padding:tile.spacingH/2;
if (zot(paddingVertical)) paddingVertical = DS.paddingVertical!=null?DS.paddingVertical:tile.spacingV/2;
if (zot(speed)) speed = DS.speed!=null?DS.speed:2;
if (zot(diagonal)) diagonal = DS.diagonal!=null?DS.diagonal:false;
if (zot(dim)) dim = DS.dim!=null?DS.dim:false;
if (zot(keyArrows)) keyArrows = DS.keyArrows!=null?DS.keyArrows:true;
if (zot(behind)) behind = DS.behind!=null?DS.behind:false;
if (zot(resizeScale)) resizeScale = DS.resizeScale!=null?DS.resizeScale:false;
if (zot(selectedIndex)) selectedIndex = DS.selectedIndex!=null?DS.selectedIndex:0;
var that = this;
var originalIndex = selectedIndex;
var tempIndex = zot(selectedIndex)||selectedIndex<0?0:selectedIndex;
var currentItem = tile.getChildAt(tempIndex);
that.currentItem = tile.getChildAt(tempIndex);
selectedIndex = originalIndex;
var target = currentItem;
var targetW = target.width+paddingHorizontal*2;
var targetH = target.height+paddingVertical*2;
that.tile = tile.addTo(that).cur();
var selector = this.selector = new Rectangle(targetW, targetH, backgroundColor, borderColor, borderWidth, corner, dashed, {ignoreScale:!resizeScale})
.centerReg(that)
.loc(target.x+paddingHorizontal, target.y+paddingVertical, that, behind?0:1);
if (selectedIndex < 0 || zot(currentItem)) selector.visible = false;
tile.mov(paddingHorizontal, paddingVertical);
this.setBounds(tile.width+paddingHorizontal*2, tile.height+paddingVertical*2);
tile.on("mousedown", function (e) {
selector.visible = true;
var target = e.target;
var tries = 0;
while(target.parent != tile && tries < 10) {target = target.parent; tries++;}
if (target.parent == tile) go(target);
});
function go(target, doAnimate) {
currentItem = target;
selectedIndex = target.tileNum;
that.animating = true;
var point = tile.localToLocal(target.x, target.y, that);
var dX = Math.abs(point.x-selector.x);
var dY = Math.abs(point.y-selector.y);
var s = doAnimate?0:speed;
if (diagonal || (dX+dY)*s <= 0) {
selector.animate({x:point.x, y:point.y},(dY+dX)*s);
} else {
if (dX>=dY) {
selector.animate([
{props:{x:point.x}, time:Math.max(100,dX*s)},
{props:{y:point.y}, time:Math.max(100,dY*s)}
])
} else {
selector.animate([
{props:{y:point.y}, time:Math.max(100,dY*s)},
{props:{x:point.x}, time:Math.max(100,dX*s)}
])
}
}
selector.animate({
props:{widthOnly:target.width+paddingHorizontal*2, heightOnly:target.height+paddingVertical*2},
time:Math.max(200,(dY+dX)*s),
call:function () {
that.animating = false;
that.dispatchEvent("change");
}
});
if (dim) {
if (dim === true) var d = .7;
else d = zim.constrain(d, 0, 1);
tile.animate({
props:{alpha:d},
rewind:true,
time:(dY+dX)*speed*.7
});
}
tile.stage.update();
}
if (keyArrows) {
that.added(function () {
that.stage.frame.on("keydown", function (e) {
if (!that.stage) return;
if (that.animating) return;
if ((that.zimAccessibility && that.focus) || (!that.zimAccessibility && that.keyFocus)) {
var answer = zim.loop(tile.items2D, function (row, j) {
var answer = zim.loop(row, function (item, i) {
if (item == currentItem) {return [i,j];}
});
if (Array.isArray(answer)) return answer;
});
var colLength = tile.items2D[answer[1]].length;
var rowLength = tile.items2D.length;
if (e.keyCode == "39") {
var newIndex = (answer[0]+1)%colLength;
go(tile.items2D[answer[1]][newIndex], newIndexanswer[0]);
} else if (e.keyCode == "38") {
var newIndex = (answer[1]-1+rowLength)%rowLength;
go(tile.items2D[newIndex][answer[0]], newIndex>answer[1]);
} else if (e.keyCode == "40") {
var newIndex = (answer[1]+1)%rowLength;
go(tile.items2D[newIndex][answer[0]], newIndex 180) angle = 0;
else if (angle-lastA < -180) angle = 359;
}
setValue(angle);
lastA = angle;
lastX = p.x;
});
upEvent = this.on("pressup", function(e) {
var deltaTime = new Date().getTime()-pressTime;
if (deltaTime < 200) {
p = that.parent.globalToLocal(e.stageX/zim.scaX, e.stageY/zim.scaY);
dX = p.x-that.x;
dY = that.y-p.y;
var angle = Math.atan2(dX,dY)*180/Math.PI;
setValue(angle);
}
lastAngle = indicator.rotation;
that.off("pressmove", moveEvent);
that.off("pressup", upEvent);
});
});
function sign(n) {return n > 0 ? 1 : -1;}
function setAccessibility() {
if (that.zimAccessibility) that.zimAccessibility.changeTitle(that, null, true);
}
function setValue(angle) {
if (continuous) {
if (resetContinuous) { // if coming from keyup
// lastContinuous = angle; // removed in 7.0.1
resetContinuous = false;
}
if (angle > lastContinuous + 180) {
continuousBase -= 360;
} else if (angle < lastContinuous - 180) {
continuousBase += 360;
}
continuousAngle = continuousBase + angle;
resetContinuousCheck = false;
var earlierValue = that.currentValue;
that.currentValue = snap(continuousAngle * (max-min) / 360);
if (earlierValue != that.currentValue) that.dispatchEvent("change");
lastContinuous = angle;
resetContinuousCheck = true;
return true;
}
var v; // value (not including min)
if (angle < 0) angle += 360;
angle = angle % 360;
if (step != 0) {
angle = Math.min(angle, 360 - 360 / (stepsTotal+1));
v = snap(angle / (360 - 360 / (stepsTotal+1)) * (max - min));
indicator.rotation = v * (360 - 360 / (stepsTotal+1)) / (max - min);
} else {
indicator.rotation = angle;
v = (angle / 360) * (max - min);
}
if (v != lastValue) {
lastValue = v;
myValue = v + min;
that.dispatchEvent("change");
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
setAccessibility();
}
var myDampedValue;
var dampObject;
if (damp) {
myDampedValue = min;
dampObject = new zim.Damp(myDampedValue, damp);
that.ticker = zim.Ticker.add(function () {
myDampedValue = dampObject.convert(myValue);
});
}
Object.defineProperty(this, 'currentValue', {
get: function() {
return damp?myDampedValue:myValue;
},
set: function(value) {
if(zot(value)) return;
if (continuous) {
continuousAdjust = false;
if (!zot(continuousMin) && !zot(continuousMax)) {
if (continuousMin < continuousMax) {
if (value < continuousMin) {value = continuousMin; continuousAdjust = true;}
if (value > continuousMax) {value = continuousMax; continuousAdjust = true;}
} else {
if (value > continuousMin) {value = continuousMin; continuousAdjust = true;}
if (value < continuousMax) {value = continuousMax; continuousAdjust = true;}
}
} else if (!zot(continuousMin)) {
if (value < continuousMin) {value = continuousMin; continuousAdjust = true;}
} else if (!zot(continuousMax)) {
if (value > continuousMax) {value = continuousMax; continuousAdjust = true;}
}
if (resetContinuousCheck) {
resetContinuous = true;
continuousBase = Math.floor(value / (max-min)) * 360;
}
} else {
if (min < max) {
if (value < min) value = limit?min:max;
if (value > max) value = limit?max:min;
} else {
if (value > min) value = limit?min:max;
if (value < max) value = limit?max:min;
}
}
myValue = value;
value = snap(value);
if (damp) damp.immediate(myValue);
indicator.rotation = (value - min) * 360 / (max - min + (continuous?0:sign(max - min)*step));
indicator.rotation = (indicator.rotation + 360 * 10000) % 360;
lastValue = value - min;
lastA = indicator.rotation;
setAccessibility();
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
Object.defineProperty(this, 'currentValueEvent', {
get: function() {
return damp?myDampedValue:myValue;
},
set: function(value) {
if (value != that.currentValue) {
that.currentValue = value;
that.dispatchEvent("change");
}
}
});
Object.defineProperty(this, 'min', {
get: function() {
return min;
},
set: function(value) {
if (continuous) min = value;
else if (zon) zogy("Dial() - min is read only");
}
});
Object.defineProperty(this, 'max', {
get: function() {
return max;
},
set: function(value) {
if (continuous) max = value;
else if (zon) zogy("Dial() - max is read only");
}
});
Object.defineProperty(this, 'continuous', {
get: function() {
return continuous;
},
set: function(value) {
if (zon) zogy("Dial() - continuous is read only");
}
});
Object.defineProperty(this, 'continuousMin', {
get: function() {
return continuousMin;
},
set: function(value) {
continuousMin = value;
if (that.currentValue < continuousMin) that.currentValue = continuousMin;
}
});
Object.defineProperty(this, 'continuousMax', {
get: function() {
return continuousMax;
},
set: function(value) {
continuousMax = value;
if (that.currentValue > continuousMax) that.currentValue = continuousMax;
}
});
Object.defineProperty(this, 'step', {
get: function() {
return step;
},
set: function(value) {
if (zon) zogy("Dial() - step is read only");
}
});
Object.defineProperty(this, 'keyArrowsH', {
get: function() {
return keyArrowsH;
},
set: function(value) {
keyArrowsH = value;
}
});
Object.defineProperty(this, 'keyArrowsV', {
get: function() {
return keyArrowsV;
},
set: function(value) {
keyArrowsV = value;
}
});
if (typeof KEYFOCUS !== typeof undefined) zim.KEYFOCUS = KEYFOCUS;
Object.defineProperty(this, 'keyFocus', {
get: function() {
return zim.KEYFOCUS == that;
},
set: function(value) {
zim.KEYFOCUS = that;
}
});
if (keyArrows && !zim.KEYFOCUS) setFocus();
this.on("mousedown", function() {if (keyArrows) setFocus()});
function setFocus() {that.keyFocus = true; var d=document.activeElement; if (d) d.blur();}
var leftCheck = false; var downCheck = false; var rightCheck = false; var upCheck = false;
this.keyDownEvent = function(e) {
if (!that.stage) return;
if ((that.zimAccessibility && that.focus) || (!that.zimAccessibility && that.keyFocus)) {
if (e.keyCode == 37 && keyArrowsH) leftCheck = true;
else if (e.keyCode == 40 && keyArrowsV) downCheck = true;
else if (e.keyCode == 39 && keyArrowsH) rightCheck = true;
else if (e.keyCode == 38 && keyArrowsV) upCheck = true;
if (that.keyInterval == null && (leftCheck || downCheck || rightCheck || upCheck)) {
checkKey();
// add traditional keydown delay
that.keyTimeout = setTimeout(function() {
if (that.keyInterval == null && (leftCheck || downCheck || rightCheck || upCheck)) that.keyInterval = setInterval(checkKey, 40);
}, 140);
}
}
}
function checkKey() {
if (leftCheck || downCheck) {
if (step > 0) that.currentValueEvent -= step * sign(max-min);
else that.currentValueEvent -= keyArrowsStep * sign(max-min);
}
if (rightCheck || upCheck) {
if (step > 0) that.currentValueEvent += step * sign(max-min);
else that.currentValueEvent += keyArrowsStep * sign(max-min);
}
}
window.addEventListener("keydown", this.keyDownEvent);
that.keyUpEvent = function(e) {
if (e.keyCode == 37) leftCheck = false;
else if (e.keyCode == 40) downCheck = false;
else if (e.keyCode == 39) rightCheck = false;
else if (e.keyCode == 38) upCheck = false;
if (that.keyInterval != null && !leftCheck && !downCheck && !rightCheck && !upCheck) {
clearInterval(that.keyInterval);
that.keyInterval = null;
}
}
window.addEventListener("keyup", this.keyUpEvent);
this._enabled = true;
Object.defineProperty(that, 'enabled', {
get: function() {
return that._enabled;
},
set: function(value) {
zenable(that, value);
if (value) {
that.keyDownEvent = window.addEventListener("keydown", that.keyDownEvent);
that.keyUpEvent = window.addEventListener("keyup", that.keyUpEvent);
} else {
window.removeEventListener("keydown", that.keyDownEvent);
window.removeEventListener("keyup", that.keyUpEvent);
}
}
});
if (zot(currentValue)) currentValue=DS.currentValue!=null?DS.currentValue:min;
that.currentValue = currentValue;
if (style!==false) zimStyleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.Dial(min, max, step, width, backgroundColor, indicatorColor, indicatorScale, indicatorType, innerCircle, innerScale, useTicks, innerTicks, tickColor, limit, keyArrows, keyArrowsStep, keyArrowsH, keyArrowsV, continuous, continuousMin, continuousMax, damp, currentValue, style, this.group, inherit));
}
this.dispose = function(a,b,disposing) {
window.removeEventListener("keydown", that.keyDownEvent);
window.removeEventListener("keyup", that.keyUpEvent);
if (!disposing) this.zimContainer_dispose(true);;
return true;
}
}
zim.extend(zim.Dial, zim.Container, ["clone", "dispose"], "zimContainer", false);
//-63
//***************** RADIAL 64
/*--
zim.Tabs = function(width, height, tabs, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, color, rollColor, selectedColor, selectedRollColor, vertical, spacing, currentEnabled, currentSelected, corner, base, keyEnabled, gradient, gloss, backing, rollBacking, wait, waitTime, waitBackgroundColor, rollWaitBackgroundColor, waitColor, rollWaitColor, waitModal, waitEnabled, backdropColor, align, valign, labelAlign, labelValign, labelIndent, labelIndentHorizontal, labelIndentVertical, indent, useTap, excludeCustomTap, selectedIndex, style, group, inherit)
Tabs
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
A traditional tab layout for along the edge of content.
Can also act as an independent button row or column.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var tabs = new Tabs({tabs:["A", "B", "C", "D"], spacing:5, corner:14});
tabs.center(stage);
tabs.on("change", function() {
zog(tabs.selectedIndex);
zog(tabs.text);
});
stage.update();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - (default 240) overall width of tab set (ZIM divides the width across tabs and spacing)
height - (default 60) height of tabs
tabs - (default ["1","2","3","4"]) an array of any String, Number, Label, Button, (or any DisplayObject)
OR tab objects with the following properties available:
any tab specific properties will override the default values from other parameters
[{label:"String", width:200, backgroundColor:"red", rollBackgroundColor:"pink", selectedBackgroundColor:"grey", color:"yellow", selectedColor:"lime"}, {etc.}]
label can be a String or a Label object - default text color is white
Tab objects can also include wait properties for individual buttons.
(this was put in place before Buttons were allowed in the tabs array - so you can just add a Button to the tab array instead)
See wait, waitTime, waitBackgroundColor, rollWaitBackgroundColor, waitColor, rollWaitColor, waitModal and waitEnabled parameters below
wait can be used with button's waiting property to offer an alternative to a loading screen or confirmation panel
also see the button's clearWait() method to cancel the wait state and waited event that triggers when the wait is done
wait will primarily be applicable when the tabs are used as a set of buttons rather than traditional tabbing
Warning - do not use the same array for multiple tabs as the array is turned into an array of objects used by the Tabs object.
backgroundColor - (default "#777") the background color of a deselected tab when not rolled over
rollBackgroundColor - (default "#555") the rollover background color
selectedBackgroundColor - (default "#333") the background color of the selected tab (any CSS color)
selectedRollBackgroundColor - (default rollBackgroundColor) the background color of the selected tab on rollover (if currentEnabled is true)
color - (default "white") the text color of a deselected tab when not rolled over
rollColor - (default color) the rollover color (selected tabs do not roll over)
selectedColor - (default color) the text color of the selected tab (any CSS color)
selectedRollColor - (default rollColor) the text color of the selected tab on rollover (if currentEnabled is true)
vertical - (default false) set to true to make vertical tabs with text still horizontal
spacing - (default 1) is the pixels between tab buttons
currentEnabled - (default false) set to true to be able to press (a second time) the selected tab button
currentSelected - (default true) set to false to not highlight the current button (good for button bars)
setting this to true will set currentEnabled to true
corner - (default 0) the corner radius of the tabs
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
base - (default "none") specifiy a side for flat bottom when corner is set (but not set to an array)
other values are "bottom" (default when corner and not vertical), "left" (default when corner and vertical), "top", "right"
** this was flatBottom - but then vertical tabs were added so it was changed in ZIM 9.2.0
keyEnabled - (default true) so tab key cycles through tabs, shift tab backwards
gradient - (default null) 0 to 1 (try .3) adds a gradient to the tabs
gloss - (default null) 0 to 1 (try .1) adds a gloss to the tabs
wait - (default null) String text for tab to say when pressed to enter a wait mode
The wait parameters can be (and probably will be) set as properties for each individual tab in the tabs array
waitTime - (default 20000) milliseconds to stay in wait state before returning to normal tab
waitBackgroundColor - (default color) the color of the tab during wait period
rollWaitBackgroundColor - (default color) the color of the tab during wait period
waitBackgroundColor - (default red) color to make button during wait time if wait is set
rollWaitBackgroundColor - (default rollColor) color for button when waiting and rolled over
waitColor - (default label's color) color to make text during wait time if wait is set
rollWaitColor - (default label's roll color) color for text when waiting and rolled over
waitModal - (default false) set to true to exit wait state if user clicks off tabs or to another tab
waitEnabled - (default true) set to false to disable tabs while in wait mode
backdropColor - (default null) set to a color to show behind the tabs (handy for when corner is not 0)
align - (default "center") horizontal align
valign - (default "center") vertical align
labelAlign - (default "center") horizontal align of the label only
labelValign - (default "center") vertical align of the label only
labelIndent - (default indent) indent of label when align or valign is set - usually same as indent unless custom objects are in tabs
labelIndentHorizontal - (default indent) horizontal indent of label when align or valign is set
labelIndentVertical - (default indent) vertical indent of label when align or valign is set
indent - (default 10) indent of items when align or valign is set and there are custom objects in tabs
useTap - (default false) set to true to use tap to activate otherwise uses ACTIONEVENT (mousedown or click)
excludeCustomTap - (default false) set to true to exclude custom buttons from tap() which would override existing tap() on the buttons
selectedIndex - (default 0) - set the selectedIndex at start
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
addAt(items, index, setStyle) - an array of items to insert at an index in the tab - tabs will grow in size - returns the object for chaining
To keep the same size - run insertAt() and then remake the Tabs using the tabs.buttons array as the tabs parameter
Can also send in a setStyle object literal {} with color, rollColor, selectedColor and selectedRollColor plus the background color versions of these!
removeAt(index, number) - remove a tab index an number of items (default 1) - tabs will shrink in size - returns the object for chaining
first() - select first tab - returns object to chain
last() - select last tab - returns object to chain
getItemIndex(item) - gets the index of the list item provided
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
selectedIndex - gets or sets the selected index of the tabs
selected - gets the selected button - selected.enabled = true, etc.
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
tabs - gets or sets tabs object (will have to manually change buttons as well as adjust props)
backgroundColor - gets or sets default unselected background color - not applied to custom buttons
rollBackgroundColor - gets or sets default rolled over background color - not applied to custom buttons
selectedBackgroundColor - gets or sets default selected background color - not applied to custom buttons
selectedRollBackgroundColor - gets or sets default selected roll background color - not applied to custom buttons
color - gets or sets default unselected text color - not applied to custom buttons
rollColor - gets or sets default rolled over text color - not applied to custom buttons
selectedColor - gets or sets default selected text color - not applied to custom buttons
selectedRollColor - gets or sets default selected roll text color - not applied to custom buttons
text - gets current selected label text
label - gets current selected label object
buttons - an array of the ZIM Button objects. buttons[0].enabled = false;
labels - an array of the ZIM Label objects. labels[0].text = "YUM"; labels[2].y -= 10;
buttonDown - the button that is currently being pressed
backdrop - reference to backdrop Rectangle if backdropColor is provided
keyEnabled - gets or sets whether the tab key and shift tab key cycles through tabs (does not affect accessibility)
enabled - default is true - set to false to disable
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
keyFocus - get or set the keyboard focus on the component - see also zim.KEYFOCUS
will be set to true if this component is the first made or component is the last to be used
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
OPTIMIZED
This component is affected by the general OPTIMIZE setting (default is false)
if set to true, you will have to stage.update() after setting certain properties
and stage.update() in change event to see component change its graphics
ACTIONEVENT
This component is affected by the general ACTIONEVENT setting
The default is "mousedown" - if set to something else the component will act on click (press)
EVENTS
dispatches a "change" event when a tab changes (but not when setting selectedIndex property)
ALSO: See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+65
zim.Tabs = function(width, height, tabs, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, color, rollColor, selectedColor, selectedRollColor, vertical, spacing, currentEnabled, currentSelected, corner, base, keyEnabled, gradient, gloss, backing, rollBacking, wait, waitTime, waitBackgroundColor, rollWaitBackgroundColor, waitColor, rollWaitColor, waitModal, waitEnabled, backdropColor, align, valign, labelAlign, labelValign, labelIndent, labelIndentHorizontal, labelIndentVertical, indent, useTap, excludeCustomTap, selectedIndex, style, group, inherit) {
var sig = "width, height, tabs, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, color, rollColor, selectedColor, selectedRollColor, vertical, spacing, currentEnabled, currentSelected, corner, base, keyEnabled, gradient, gloss, backing, rollBacking, wait, waitTime, waitBackgroundColor, rollWaitBackgroundColor, waitColor, rollWaitColor, waitModal, waitEnabled, backdropColor, align, valign, labelAlign, labelValign, labelIndent, labelIndentHorizontal, labelIndentVertical, indent, useTap, excludeCustomTap, selectedIndex, style, group, inherit";
var duo; if (duo = zob(zim.Tabs, arguments, sig, this)) return duo;
z_d("65");
var DS = style===false?{}:zim.getStyle("Tabs", group, inherit);
if (zot(vertical)) vertical = DS.vertical!=null?DS.vertical:false;
var specifiedWidth = !zot(width);
if (zot(width)) width = DS.width!=null?DS.width:(vertical?60:240);
if (zot(height)) height = DS.height!=null?DS.height:(vertical?240:60);
this.zimContainer_constructor(null,null,null,null,true);
this.type = "Tabs";
this.group = group;
if (zot(tabs) || tabs.length<=0) tabs = DS.tabs!=null?DS.tabs:[1,2,3,4];
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"#777";
if (zot(rollBackgroundColor)) rollBackgroundColor = DS.rollBackgroundColor!=null?DS.rollBackgroundColor:"#555";
if (zot(selectedBackgroundColor)) selectedBackgroundColor = DS.selectedBackgroundColor!=null?DS.selectedBackgroundColor:"#333";
if (zot(selectedRollBackgroundColor)) selectedRollBackgroundColor = DS.selectedRollBackgroundColor!=null?DS.selectedRollBackgroundColor:rollBackgroundColor;
if (zot(color)) color = DS.color!=null?DS.color:"white";
if (zot(rollColor)) rollColor = DS.rollColor!=null?DS.rollColor:color;
if (zot(selectedColor)) selectedColor = DS.selectedColor!=null?DS.selectedColor:color;
if (zot(selectedRollColor)) selectedRollColor = DS.selectedRollColor!=null?DS.selectedRollColor:rollColor;
if (zot(backing)) backing = DS.backing!=null?DS.backing.clone():null;
if (zot(rollBacking)) rollBacking = DS.rollBacking!=null?DS.rollBacking.clone():null;
if (zot(align)) align=DS.align!=null?DS.align:"center";
if (zot(valign)) valign=DS.valign!=null?DS.valign:"center";
if (zot(labelAlign)) labelAlign=DS.labelAlign!=null?DS.labelAlign:align;
if (zot(labelValign)) labelValign=DS.labelValign!=null?DS.labelValign:valign;
if (zot(indent)) indent=DS.indent!=null?DS.indent:10;
if (zot(labelIndent)) labelIndent=DS.labelIndent!=null?DS.labelIndent:indent;
if (zot(labelIndentHorizontal)) labelIndentHorizontal=DS.labelIndentHorizontal!=null?DS.labelIndentHorizontal:labelIndent;
if (zot(labelIndentVertical)) labelIndentVertical=DS.labelIndentVertical!=null?DS.labelIndentVertical:labelIndent;
if (zot(currentEnabled)) currentEnabled = DS.currentEnabled!=null?DS.currentEnabled:false;
if (zot(currentSelected)) {
currentSelected = DS.currentSelected!=null?DS.currentSelected:true; // keep the highlight on after pressup
}
if (!currentSelected) currentEnabled = true; // button bar
if (zot(spacing)) spacing = DS.spacing!=null?DS.spacing:1;
if (zot(corner)) corner = DS.corner!=null?DS.corner:0;
if (zot(gradient)) gradient = DS.gradient!=null?DS.gradient:null;
if (zot(gloss)) gloss = DS.gloss!=null?DS.gloss:null;
if (zot(base)) base = DS.base!=null?DS.base:((corner==0&&!Array.isArray(corner))?"none":(vertical?"left":"bottom"));
if (zot(keyEnabled)) keyEnabled = DS.keyEnabled!=null?DS.keyEnabled:true;
if (zot(useTap)) useTap = DS.useTap!=null?DS.useTap:false;
if (zot(excludeCustomTap)) excludeCustomTap = DS.excludeCustomTap!=null?DS.excludeCustomTap:false;
if (zot(backdropColor)) backdropColor = DS.backdropColor!=null?DS.backdropColor:null;
if (base != "none" && corner!=0 && !Array.isArray(corner)) {
switch(base) {
case "bottom":
corner = [corner, corner, 0, 0]; break;
case "left":
corner = [0, corner, corner, 0]; break;
case "top":
corner = [0, 0, corner, corner]; break;
case "right":
corner = [corner, 0, 0, corner]; break;
}
} else if (!Array.isArray(corner)) {
corner = [corner, corner, corner, corner];
}
var that = this;
this.keyEnabled = keyEnabled;
var myIndex = 0; // local value for this.selectedIndex
var labels = []
var buttons = [];
var button; var t;
var num = tabs.length;
var tabW = (width - spacing*(num-1))/num;
var tabH = (height - spacing*(num-1)-2)/num;
if (!zot(backdropColor)) {
// may be resized later
var backdrop = this.backdrop = new zim.Rectangle(width,height,backdropColor, null, null, null, null, null, false);
this.addChild(backdrop);
}
// Make a list be tab data objects if string, number, label or {} - other objects are ignored
var mix = false; // used to determine how to treat indent
var mixType;
function makeDataObject(list) {
for (var i=0; i width - spacing*(num-1)) {
// go back and assign proportional widths
for (i=0; i 0) {
newTabW = (num*tabW-(total-nonSpecifiedCount*tabW))/nonSpecifiedCount;
for (i=0; i maxWidth) maxWidth = t.label.width;
}
// create buttons
var hMaxWidth = 0;
function makeButtons(list, addStyle) {
var buttons = [];
var labels = [];
for (i=0; i hMaxWidth) hMaxWidth = button.width;
// apply events
if (useTap) {
button.tap(function (e) {
change(e.currentTarget.znum);
that.dispatchEvent("change");
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
})
} else {
button.zimTabEvent = button.on((!zns?ACTIONEVENT=="mousedown":zim.ACTIONEVENT=="mousedown")?"mousedown":"click", function(e) {
change(e.currentTarget.znum);
that.dispatchEvent("change");
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
});
}
button.on("mousedown", function(e) {
that.buttonDown = e.currentTarget;
});
button.on("pressup", function() {
that.buttonDown = null;
});
labels.push(t.label);
buttons.push(button);
button.index = i;
}
return [buttons, labels];
}
var result = makeButtons(tabs);
buttons = result[0];
labels = result[1];
// finalize index, location, bounds
function prepareAllButtons() {
var lastX = 0; var lastY = 0; var t; var button;
for (i=0; i= index && myIndex <= index+num) myIndex = -1;
if (myIndex > index+num) myIndex -= num;
// remove listeners
for (i=index; itabs.length-1)?0:next);
}
that.dispatchEvent("change");
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
e.preventDefault();
}
});
Object.defineProperty(this, 'selected', {
get: function() {
return buttons[myIndex];
},
set: function(value) {
if (zon) zogy("Tabs() - selected is read only - try selectedIndex");
}
});
Object.defineProperty(this, 'selectedIndex', {
get: function() {
return myIndex;
},
set: function(value) {
// change(Math.min(Math.max(value, 0), tabs.length-1));
change(value);
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
this.last = function() {
this.selectedIndex = this.buttons.length-1;
return this;
}
this.first = function() {
this.selectedIndex = 0;
return this;
}
Object.defineProperty(this, 'tabs', {
get: function() {
return myIndex;
},
set: function(value) {
change(Math.min(Math.max(value, 0), tabs.length-1));
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
Object.defineProperty(this, 'color', {
get: function() {
if (that.buttons[0].tabItems) return that.buttons[0].tabItems.color;
else return color;
},
set: function(value) {
color = value;
if (that.buttons[0].tabInfo) {
for (var i=0; i= 0 && tabNum < that.tabs.length) {
that.tabs[tabNum].selectedIndex = myIndex % cols;
}
}
});
this._enabled = true;
Object.defineProperty(that, 'enabled', {
get: function() {
return that._enabled;
},
set: function(value) {
zenable(that, value);
}
});
if (zot(selectedIndex)) selectedIndex=DS.selectedIndex!=null?DS.selectedIndex:0;
that.selectedIndex = selectedIndex;
if (style!==false) zimStyleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.Pad(width, cols, rows, keys, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, color, rollColor, selectedColor, selectedRollColor, spacing, currentEnabled, corner, labelColor, gradient, gloss, backing, rollBacking, wait, waitTime, waitBackgroundColor, rollWaitBackgroundColor, waitColor, rollWaitColor, waitModal, waitEnabled, selectedIndex, style, this.group, inherit));
}
}
zim.extend(zim.Pad, zim.Container, "clone", "zimContainer", false);
//-66
//
/*--
zim.DPad = function(axis, width, backgroundColor, borderWidth, borderColor, indicatorColor, indicatorPressColor, indicatorScale, indicatorRadius, innerCircle, innerScale, activeRadius, clamp, logo, style, group, inherit)
DPad
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
A DPad (Directional Pad) can be used to control x and y values
This is primarily handy on mobile where a substitute for keypresses is needed
The DPad can be set up for all directions, horizontal or vertical
The DPad can be passed in to a ZIM MotionController to control an object
See: https://zimjs.com/ten/dpad.html
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var dPadH = new DPad().pos(50,50,false,true);
new MotionController({
target:new Circle().center(),
type:dPadH,
speed:mobile()?100:80,
boundary:new Boundary(0,0,stageW,stageH)
});
stage.update();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
axis - (default "all") set to "horizontal" or "vertical" or "all". Appropriate arrows will show
width - (default 100) width of DPad backgroundColor - (default "#777") the background color of a deselected key when not rolled over
backgroundColor - (default "#666") the background color (any zim or html color)
indicatorColor - (default "#ddd") the color of the arrows
indicatorPressColor - (default "#eee") the color of the arrows as pressed
indicatorScale - (default 1) the scale of the arrows
indicatorRadius - (default null) set the indicator radius
innerCircle - (default true) set to false to not show an inner circle
innerScale - (default .5) the scale relative to the indicator
activeRadius - (default width*2) radius at which the DPad works
clamp - (default true) set to false to not limit the value between -1 and 1
logo - (default false) set to true to show the letter D in the DPad - or add your own
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
dirX, dirY - the x and y values for the DPad - between -1 and 1 if clamp is set
these can be multiplied by a factor to adjust speed - or use speed parameter of associated MotionController
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
enabled - default is true - set to false to disable
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
dispatches a "change" event with dirX and dirY provided as well on the event object
ALSO: See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+66.2
zim.DPad = function(axis, width, backgroundColor, borderWidth, borderColor, indicatorColor, indicatorPressColor, indicatorScale, indicatorRadius, innerCircle, innerScale, activeRadius, clamp, logo, style, group, inherit) {
var sig = "axis, width, backgroundColor, borderWidth, borderColor, indicatorColor, indicatorPressColor, indicatorScale, indicatorRadius, innerCircle, innerScale, activeRadius, clamp, logo, style, group, inherit";
var duo; if (duo = zob(zim.DPad, arguments, sig, this)) return duo;
z_d("66.2");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "DPad";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(axis)) axis = DS.axis!=null?DS.axis:"all";
if (zot(width)) width = DS.width!=null?DS.width:100;
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"#666666";
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:null;
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:null;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = 1;
if (zot(indicatorColor)) indicatorColor = DS.indicatorColor!=null?DS.indicatorColor:"#dddddd";
if (zot(indicatorPressColor)) indicatorPressColor = DS.indicatorPressColor!=null?DS.indicatorPressColor:"#eeeeee";
if (zot(indicatorScale)) indicatorScale = DS.indicatorScale!=null?DS.indicatorScale:1;
if (zot(indicatorRadius)) indicatorRadius = DS.indicatorRadius!=null?DS.indicatorRadius:null;
if (zot(innerCircle)) innerCircle = DS.innerCircle!=null?DS.innerCircle:true;
if (zot(innerScale)) innerScale = DS.innerScale!=null?DS.innerScale:.5;
if (zot(activeRadius)) activeRadius = DS.activeRadius!=null?DS.activeRadius:width; // note, twice diameter
if (zot(clamp)) clamp = DS.clamp!=null?DS.clamp:true;
if (zot(logo)) logo = DS.logo!=null?DS.logo:false;
var that = this;
this.axis = axis;
var outer = this.outer = new zim.Circle(width/2, backgroundColor, borderColor, borderWidth).addTo(this);
var inner = this.inner = new zim.Circle(width*innerScale/2, "rgba(0,0,0,.2)").center(this);
if (logo) this.logo = new zim.Label({text:"D", fontOptions:"bold"}).center(inner).mov(1,2).alp(.3);
var arrows = new zim.Container().addTo(this);
var arrowSize = (width-borderWidth)*.2*indicatorScale;
var numArrows = 8; // default all
if (axis == "vertical") {
numArrows = 2;
} else if (axis == "horizontal") {
numArrows = 2;
arrows.rotation = 90;
} else if (axis == "both") {
numArrows = 4;
}
zim.loop(numArrows, function (i, total) {
new Triangle(arrowSize, arrowSize, arrowSize, indicatorColor).addTo(arrows).reg(null, zot(indicatorRadius)?(width-borderWidth)*.475:indicatorRadius).rot(i*360/total);
});
var startX = 0;
var startY = 0;
var stage;
var p;
var currentEvent;
var firstTime = true;
this.on("mousedown", function (e) {
stage = e.target.stage;
currentEvent = e;
arrows.loop(function (arrow) {
arrow.color = indicatorPressColor;
});
if (firstTime) {
that.ticker = zim.Ticker.add(function () {
calculatePos();
});
} else {
zim.Ticker.add(that.ticker);
}
});
this.on("pressmove", function (e) {
currentEvent = e;
});
this.on("pressup", function (e) {
zim.Ticker.remove(that.ticker);
that.dirX = that.dirY = 0;
arrows.loop(function (arrow) {
arrow.color = indicatorColor;
});
if (that.stage) stage.update();
});
function calculatePos(){
var e = currentEvent;
startX = e.stageX/zim.scaX;
startY = e.stageY/zim.scaY;
p = that.globalToLocal(startX, startY);
e = new createjs.Event("change");
e.dirX = ((p.x+activeRadius)/(activeRadius*2)-.5)*2;
e.dirY = ((p.y+activeRadius)/(activeRadius*2)-.5)*2;
if (clamp) {
e.dirX = zim.constrain(e.dirX, -1, 1);
e.dirY = zim.constrain(e.dirY, -1, 1);
}
that.dirX = e.dirX;
that.dirY = e.dirY;
that.dispatchEvent(e);
}
this._enabled = true;
Object.defineProperty(that, 'enabled', {
get: function() {
return that._enabled;
},
set: function(value) {
zenable(that, value);
}
});
zimStyleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.DPad(axis, width, backgroundColor, borderWidth, borderColor, indicatorColor, indicatorPressColor, indicatorScale, indicatorRadius, innerCircle, innerScale, activeRadius, clamp, logo, style, this.group, inherit));
}
this.dispose = function(a,b,disposing) {
if (this.ticker) zim.Ticker.remove(this.ticker);
if (!disposing) this.zimContainer_dispose(true);;
return true;
}
}
zim.extend(zim.DPad, zim.Container, ["clone", "dispose"], "zimContainer", false);
//-66.2
//
/*--
zim.Radial = function(labels, size, font, height, coreRadius, coreColor, startAngle, totalAngle, angles, flip, shiftVertical, icons, rollIcons, rotateIcons, iconsShiftVertical, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, backdropColor, color, rollColor, selectedColor, selectedRollColor, borderColor, borderWidth, gradient, gap, gapAsAngle, spacing, spacingInner, spacingOuter, currentEnabled, currentSelected, selectedIndex, style, group, inherit)
Radial
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
A radial ring with selectable buttons with lables or icons
Used internally by ZIM RadialMenu which has expandable rings for a hierarchical interface
Radial uses LabelOnArc for labels
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var radial = new Radial(["one", "two", "three", "four"]).center();
radial.change(function () {
zog(radial.selectedIndex);
});
stage.update();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports VEE - parameters marked with ZIM VEE mean a zim Pick() object or Pick Literal can be passed
Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
labels - (default ["A", "B", "C", "D", "E"]) an array of text or ZIM Label objects for buttons
size - (default 30) label size
font - (default "verdana") the font - can also import fonts in Frame() asset parameter or frame.loadAssets()
startAngle - (default null) will start first button centered at top - see also totalAngle
setting an angle will start left side of first button at this angle
with 0 being the top (note, ZIM angles usually start along x axis - but not here)
totalAngle - (default 360) set to use only a portion of the circle - see also startAngle
angles - (default null) can set an array of angles for center of the buttons
can use angles property toString() to get existing angle data
this can be modified to suit and passed into this parameter for unequal button sizes
flip - (default true) flip the text between 90 and -180 (from 0 at top)
shiftRadial - (default 0) amount to shift text in radially
icons - (default null) set to an array of objects that will go under the text
can set the labels to ["", "", "", etc.] to hide the text
icons should be centerReg({add:false}) to ensure centered placement
rollIcons - (default null) set to an array of objects to replace icon when rolled over
rotateIcons - (default false) set to true to rotate icons around radial
iconsShiftRadial - (default 0) amount to shif the icons radially
height - (default 60) height of radial - not including core
coreRadius - (default 100) the radius of the core
this is fairly large but can sca(.5) the radial after creating, etc.
coreColor - (default #333) the color of the core
backgroundColor - |ZIM VEE| - (default "#666") the background color of a button
ZIM VEE means you can specify different colors for instance: series(blue, green, red, yellow)
these would then be the color order of the buttons - same for rollBackgroundColor, etc.
rollBackgroundColor - |ZIM VEE| - (default "#777") the rollover background color of a button
selectedBackgroundColor - |ZIM VEE| - (default "#444") the background color of the selected button
selectedRollBackgroundColor - |ZIM VEE| - (default selectedBackgroundColor) the roll background color of the selected button
backdropColor - (default clear) set to change the color behind the radial - including spacingOuter
color - |ZIM VEE| - (default "white") the text color of the button
rollColor - |ZIM VEE| - (default color) the rollover text color of the button
selectedColor - |ZIM VEE| - (default color) the text color of the selected button
selectedRollColor - |ZIM VEE| - (default color) the rollover text color of the selected button
borderColor - (default #333) color of the button border
borderWidth - (default 2) width of the button border
gradient - (default null) set to a number between 0 and 1 - would suggest .1 for gradient on button
gap - (default 6 pixels or 3 degrees if gapAsAngle is true) gap between buttons
gapAsAngle - (default false) set to true set gap as angle
spacing - (default 6) radial spacing around button from core or edge of backdrop
spacingInner - (default spacing) inside radial spacing from core
spacingOuter - (default spacing) outside radial spacing from edge of backdrop
currentEnabled - (default false) set to true to make selected key pressable (for change event)
currentSelected - (default true) set to true to make selected key show selected colors
selectedIndex - (default 0) - set the selectedIndex at start
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
selectedIndex - gets or sets the selected index of the pad
text - gets current selected label text
label - gets current selected label object
selected - gets the selected button - selected.enabled = true, etc.
buttons - a container of buttons
each button has label and icon properties
angles - an array of angles to the center of the buttons
can log angles.toString() to get angle data
this can be adjusted and passed in to the angles parameter for unequal size buttons
core - a reference to the core circle object
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
enabled - default is true - set to false to disable
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
OPTIMIZED
This component is affected by the general OPTIMIZE setting (default is false)
if set to true, you will have to stage.update() after setting certain properties
and stage.update() in change event to see component change its graphics
ACTIONEVENT
This component is affected by the general ACTIONEVENT setting
The default is "mousedown" - if set to something else the component will act on click (press)
EVENTS
dispatches a "change" event when the button changes (but not when setting selectedIndex property)
see also currentEnabled to get change event for each press - or use tap()
ALSO: See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+66.4
zim.Radial = function(labels, size, font, height, coreRadius, coreColor, startAngle, totalAngle, angles, flip, shiftRadial, icons, rollIcons, rotateIcons, iconsShiftRadial, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, backdropColor, color, rollColor, selectedColor, selectedRollColor, borderColor, borderWidth, gradient, gap, gapAsAngle, spacing, spacingInner, spacingOuter, currentEnabled, currentSelected, selectedIndex, style, group, inherit) {
var sig = "labels, size, font, height, coreRadius, coreColor, startAngle, totalAngle, angles, flip, shiftRadial, icons, rollIcons, rotateIcons, iconsShiftRadial, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, backdropColor, color, rollColor, selectedColor, selectedRollColor, borderColor, borderWidth, gradient, gap, gapAsAngle, spacing, spacingInner, spacingOuter, currentEnabled, currentSelected, selectedIndex, style, group, inherit";
var duo; if (duo = zob(zim.Radial, arguments, sig, this)) return duo;
z_d("66.4");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "Radial";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(labels)) labels = DS.labels!=null?DS.labels:["A", "B", "C", "D", "E"];
if (zot(size)) size = DS.size!=null?DS.size:30;
if (zot(font)) font = DS.font!=null?DS.font:"verdana";
if (zot(startAngle)) startAngle = DS.startAngle!=null?DS.startAngle:null; // top center
if (zot(totalAngle)) totalAngle = DS.totalAngle!=null?DS.totalAngle:360;
if (zot(angles)) angles = DS.angles!=null?DS.angles:null;
if (zot(flip)) flip = DS.flip!=null?DS.flip:true;
if (zot(shiftRadial)) shiftRadial = DS.shiftRadial!=null?DS.shiftRadial:0;
if (zot(icons)) icons = DS.icons!=null?DS.icons:null;
if (zot(rollIcons)) rollIcons = DS.rollIcons!=null?DS.rollIcons:null;
if (zot(rotateIcons)) rotateIcons = DS.rotateIcons!=null?DS.rotateIcons:false;
if (zot(iconsShiftRadial)) iconsShiftRadial = DS.iconsShiftRadial!=null?DS.iconsShiftRadial:0;
if (zot(height)) height = DS.height!=null?DS.height:60;
if (zot(coreRadius)) coreRadius = DS.coreRadius!=null?DS.coreRadius:100;
if (zot(coreColor)) coreColor = DS.coreColor!=null?DS.coreColor:"#333";
if (zot(backdropColor)) backdropColor = DS.backdropColor!=null?DS.backdropColor:zim.clear;
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"#666";
if (zot(rollBackgroundColor)) rollBackgroundColor = DS.rollBackgroundColor!=null?DS.rollBackgroundColor:"#777";
if (zot(selectedBackgroundColor)) selectedBackgroundColor = DS.selectedBackgroundColor!=null?DS.selectedBackgroundColor:"#444";
if (zot(selectedRollBackgroundColor)) selectedRollBackgroundColor = DS.selectedRollBackgroundColor!=null?DS.selectedRollBackgroundColor:selectedBackgroundColor;
if (zot(color)) color = DS.color!=null?DS.color:"white";
if (zot(rollColor)) rollColor = DS.rollColor!=null?DS.rollColor:color;
if (zot(selectedColor)) selectedColor = DS.selectedColor!=null?DS.selectedColor:color;
if (zot(selectedRollColor)) selectedRollColor = DS.selectedRollColor!=null?DS.selectedRollColor:rollColor;
if (zot(borderColor)) borderColor=DS.borderColor!=null?DS.borderColor:"#333";
if (zot(borderWidth)) borderWidth=DS.borderWidth!=null?DS.borderWidth:2; // 0
if (zot(gapAsAngle)) gapAsAngle=DS.gapAsAngle!=null?DS.gapAsAngle:false;
if (zot(gap)) gap=DS.gap!=null?DS.gap:(gapAsAngle?3:6);
if (zot(gradient)) gradient=DS.gradient!=null?DS.gradient:null;
if (gradient === true) gradient = .1;
if (zot(spacing)) spacing=DS.spacing!=null?DS.spacing:6;
if (zot(spacingInner)) spacingInner=DS.spacingInner!=null?DS.spacingInner:spacing;
if (zot(spacingOuter)) spacingOuter=DS.spacingOuter!=null?DS.spacingOuter:spacing;
if (zot(currentEnabled)) currentEnabled=DS.currentEnabled!=null?DS.currentEnabled:false;
if (zot(currentSelected)) currentSelected=DS.currentSelected!=null?DS.currentSelected:true;
var that = this;
var innerRadius = this.innerRadius = coreRadius+spacingInner;
var outerRadius = this.outerRadius = innerRadius + height;
this.setBounds(-outerRadius, -outerRadius, outerRadius*2, outerRadius*2)
var backdrop = this.backdrop = new Circle(outerRadius+spacingOuter, backdropColor).center(this);
if (coreRadius > 0) this.core = new Circle(coreRadius, coreColor).center(this);
if (angles && angles.length < labels.length-1) {
if (zon) zogy("Radial() - not enough angles provided");
return this;
}
if ((labels && labels.length > 0) || (icons && icons.length > 0)) {
var total;
if (labels && labels.length > 0) total = labels.length;
if (icons && icons.length > 0) {
if (total > 0) total = Math.min(icons.length, total);
else total = icons.length;
}
if (rollIcons && rollIcons.length < total) {
for (j=0; j 0) { // no border specified or a border > 0
if (!zot(borderColor) || !zot(borderWidth)) { // either a border color or thickness
if (zot(borderColor)) borderColor = "black";
button.borderColorCommand = g.s(borderColor).command;
button.borderWidthCommand = g.ss(borderWidth).command;
}
}
var a0 = (lastAngle-90-segmentAngle/2)*Math.PI/180;
var a1 = (lastAngle-90+segmentAngle/2)*Math.PI/180;
var a2 = (lastAngle-90+(segmentAngle+gap-gapInner)/2)*Math.PI/180;
var a3 = (lastAngle-90-(segmentAngle+gap-gapInner)/2)*Math.PI/180;
g.arc(0, 0, outerRadius, a0, a1, false);
g.arc(0, 0, innerRadius, a2, a3, true).cp();
if (gradient) {
g.s().ss().rf(["rgba(0,0,0,"+gradient+")","rgba(255,255,255,"+gradient+")"], [0, 1], 0, 0, innerRadius, 0, 0, outerRadius);
g.arc(0, 0, outerRadius, a0, a1, false);
g.arc(0, 0, innerRadius, a2, a3, true).cp();
}
button.cursor = "pointer";
button.zimOverEvent = button.on("mouseover", function(e) {
var button = e.target;
button.colorCommand.style = (button==that.selected&¤tSelected)?button.selectedRollBackgroundColor:button.rollBackgroundColor;
if (button.label) button.label.color = (button==that.selected&¤tSelected)?button.selectedRollColor:button.rollColor;
if (rollIcons) {
button.holder.removeAllChildren();
rollIcons[button.num].loc(1,0,button.holder);
}
if (that.stage) that.stage.update();
});
button.zimOutEvent = button.on("mouseout", function(e) {
var button = e.target;
button.colorCommand.style = (button==that.selected&¤tSelected)?button.selectedBackgroundColor:button.backgroundColor;
if (button.label) button.label.color = (button==that.selected&¤tSelected)?button.selectedColor:button.color;
if (rollIcons) {
button.holder.removeAllChildren();
if (icons) icons[button.num].loc(1,0,button.holder);
}
if (that.stage) that.stage.update();
});
button.zimDownEvent = button.on((!zns?ACTIONEVENT=="mousedown":zim.ACTIONEVENT=="mousedown")?"mousedown":"click", function(e) {
var button = e.target;
var diff = button !== that.selected;
that.lastSelected = that.selected;
myIndex = button.num;
if (currentSelected) {
if (diff) {
if (that.selected) {
that.selected.colorCommand.style = that.selected.backgroundColor;
if (that.selected.label) that.selected.label.color = that.selected.color;
}
that.selected = button;
that.label = button.label;
if (that.label) that.text = that.label.text;
that.icon = button.icon;
button.colorCommand.style = button.selectedRollBackgroundColor;
if (button.label) button.label.color = button.selectedRollColor;
} else {
if (!currentEnabled) {
myIndex = -1;
that.selected = null;
that.label = null;
that.text = null;
that.icon = null;
button.colorCommand.style = button.rollBackgroundColor;
if (button.label) button.label.color = button.rollColor;
}
}
} else {
that.selected = button;
that.label = button.label;
if (that.label) that.text = that.label.text;
that.icon = button.icon;
}
that.dispatchEvent("change");
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
});
if (icons && icons.length > 0) {
var h = innerRadius+height/2+iconsShiftRadial;
var holder = button.holder = new zim.Container(3, h).addTo(this).reg(1,h).rot(lastAngle);
holder.mouseChildren = false;
holder.mouseEnabled = false;
button.icon = icons[i];
icons[i].loc(1,0,holder);
if (!rotateIcons) icons[i].rotation = -lastAngle;
} // end icons
if (labels && labels.length > 0) {
// var buttons = this.buttons = new zim.Container(-s/2, -s/2, s, s).centerReg(this);
var loa;
if (labels[i].type != "LabelOnArc") {
var label = (labels[i].type=="Label"?labels[i]:new Label(labels[i], size, font, color));
loa = new zim.LabelOnArc({
label: label,
color:color,
size:size,
spacing:-5,
flip:(flip && lastAngle>90 && lastAngle<270),
radius:innerRadius+(height-label.height)/2+2+shiftRadial
});
} else {
loa = labels[i];
}
labels[i] = loa;
button.label = loa;
loa.center(this).rot(lastAngle);
loa.mouseChildren = false;
loa.mouseEnabled = false;
} // end labels
if (i==labels.length-1) continue;
var segmentAngle2 = angles?angles[i+1]:segmentAngle;
lastAngle += (segmentAngle+segmentAngle2)/2+gap;
}
if (!zot(startAngle)) {
that.rotation += that.buttons.getChildAt(0).angle/2;
}
}
var myIndex = null;
Object.defineProperty(this, 'selectedIndex', {
get: function() {
return myIndex;
},
set: function(value) {
var button;
if (that.buttons) button = that.buttons.getChildAt(value);
if (button !== that.selected) {
if (that.selected) {
that.selected.colorCommand.style = that.selected.backgroundColor;
if (that.selected.label) that.selected.label.color = that.selected.color;
}
that.selected = button;
if (button) {
if (currentSelected) button.colorCommand.style = button.selectedRollBackgroundColor;
if (button.label) {
if (currentSelected) button.label.color = button.selectedColor;
that.text = button.label.text;
}
}
}
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
});
if (zot(selectedIndex)) selectedIndex=DS.selectedIndex!=null?DS.selectedIndex:0;
that.selectedIndex = selectedIndex;
zimStyleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.Radial(labels, size, font, height, coreRadius, coreColor, startAngle, totalAngle, angles, flip, shiftRadial, icons, rollIcons, rotateIcons, iconsShiftRadial, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, backdropColor, color, rollColor, selectedColor, selectedRollColor, borderColor, borderWidth, gradient, gap, gapAsAngle, spacing, spacingInner, spacingOuter, currentEnabled, currentSelected, selectedIndex, style, this.group, inherit));
}
}
zim.extend(zim.Radial, zim.Container, "clone", "zimContainer", false);
//-66.4
/*--
zim.RadialMenu = function(menu, size, font, height, coreRadius, coreColor, title, titleIcon, startAngle, totalAngle, flip, shiftRadial, rotateIcons, iconsShiftRadial, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, backdropColor, color, rollColor, selectedColor, selectedRollColor, borderColor, borderWidth, gradient, gap, gapAsAngle, spacing, spacingInner, spacingOuter, currentEnabled, currentSelected, open, under, style, group, inherit)
RadialMenu
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
An expanding hierarchy menu of button rings - using ZIM Radial objects.
The menu is specified by a menu parameter in the format of a ZIM Hierarchy object.
Styles for each ring can be specified in the menu object.
Icons for each ring can be specified in the styles.
See https://zimjs.com/ten/radial.html
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var menu = {
"one":[1,2,3,4], // an array is okay as all items are leaf nodes (end nodes)
"two":{ // an object literal is required as one or more items hold other items
"1":[], // this holds nothing (a leaf node) but still needs an empty array
"2":["a", "b", "c"], // this holds a linear list - all leaf nodes
"3":{ // this holds another nested list where at least one item holds more
"emotions":["love","hate","happy","sad"],
"flavors":["sweet","sour","bland","spicy"]
}
},
"three":[1,2,3,4,5,6],
"four":[1,2,3,4,5,6,7,8]
}
new RadialMenu(menu).sca(.5).center();
stage.update();
// OR ADD STYLES
// see https://zimjs.com/ten/radial.html for full example
// any Radial parameters can go in the styles:{} brackets
// including icons and rollIcons
// and can use series to apply background colors and colors to individual buttons
// PS - this is the EXTRA version of the simple ZIM Hierarchy format
// here we pass styles as an extra property - list is required
// styles is optional but used by ZIM RadialMenu to apply associated styles
var menu = {
list:{
"one":{
list:["A","B","C","D"], // an array is okay as all items are leaf nodes (end nodes)
styles:{backgroundColor:blue}
},
"two":{
list:{ // an object literal is required as one or more items hold other items
"1":[], // this holds nothing (a leaf node) but still needs an empty array
"2":{
list:["a", "b", "c"], // this holds a linear list - all leaf nodes
styles:{}
},
"3":{ // this holds another nested list where at least one item holds more
list:{
"emotions":{
list:["love","hate","happy","sad"],
styles:{}
},
"flavors":{
list:["sweet","sour","bland","spicy"] ,
styles:{}
}
},
styles:{}
}
},
styles:{}
},
"three":{
list:[1,2,3,4,5,6],
styles:{}
},
"four":{
list:[1,2,3,4,5,6,7,8],
styles:{}
}
},
// the styles for the first list
// here we make each backgroundColor a different color
styles:{backgroundColor:series(red,green,blue,yellow)}
}
new RadialMenu(menu).sca(.5).center();
stage.update();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports VEE - parameters marked with ZIM VEE mean a zim Pick() object or Pick Literal can be passed
Pick Literal formats: [1,3,2] - random; {min:10, max:20} - range; series(1,2,3) - order, function(){return result;} - function
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
menu - (default a simple menu) a ZIM Hierarchy (simple, simple EXTRA or complex)
that holds the menu labels and optionally styles
see the ZIM RadialMenu examples and the format descriptions of ZIM Hierarchy for details
size - (default 30) label size
font - (default "verdana") the font - can also import fonts in Frame() asset parameter or frame.loadAssets()
startAngle - (default null) will start first button centered at top - see also totalAngle
setting an angle will start left side of first button at this angle
with 0 being the top (note, ZIM angles usually start along x axis - but not here)
totalAngle - (default 360) set to use only a portion of the circle - see also startAngle
flip - (default true) flip the text between 90 and -180 (from 0 at top)
shiftRadial - (default 0) amount to shift text in radially
rotateIcons - (default false) set to true to rotate icons around radial
iconsShiftRadial - (default 0) amount to shif the icons radially
height - (default 60) height of radial - not including core or previous radials
coreRadius - (default 100) the radius of the core
this is fairly large but can sca(.5) the radial after creating, etc.
coreColor - (default #333) the color of the core
title - (default "MENU") the label text in the core
titleIcon - (default null) an object to put under the title
** FOR BELOW: see menu parameter where colors can be set per ring and per button for ZIM VEE colors
backgroundColor - |ZIM VEE| - (default "#666") the background color of a button
ZIM VEE means you can specify different colors for instance: series(blue, green, red, yellow)
these would then be the color order of the buttons - same for rollBackgroundColor, etc.
rollBackgroundColor - |ZIM VEE| - (default "#777") the rollover background color of a button
selectedBackgroundColor - |ZIM VEE| - (default "#444") the background color of the selected button
selectedRollBackgroundColor - |ZIM VEE| - (default selectedBackgroundColor) the roll background color of the selected button
backdropColor - (default clear) set to change the color behind the radial - including spacingOuter
color - |ZIM VEE| - (default "white") the text color of the button
rollColor - |ZIM VEE| - (default color) the rollover text color of the button
selectedColor - |ZIM VEE| - (default color) the text color of the selected button
selectedRollColor - |ZIM VEE| - (default color) the rollover text color of the selected button
borderColor - (default #333) color of the button border
borderWidth - (default 2) width of the button border
gradient - (default null) set to a number between 0 and 1 - would suggest .1 for gradient on button
gap - (default 6 pixels or 3 degrees if gapAsAngle is true) gap between buttons
gapAsAngle - (default false) set to true set gap as angle
spacing - (default 6) radial spacing around button from core or edge of backdrop
spacingInner - (default spacing) inside radial spacing from nearest inside object
spacingOuter - (default spacing) outside radial spacing from edge of backdrop
currentEnabled - (default false) set to true to make selected key pressable (for change event)
currentSelected - (default true) set to true to make selected key show selected colors
open - (default false) set to true to start with first menu open
under - (default true) set to false to open menu rings in the top layer (usually under just in case there is a backdrop)
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
closeRings(num) - close menu rings - default is all rings but use 1 to close the outer ring, 2 to close the two outer rings, etc.
see the outerLevel property for the current outer ring number with core being 0
opening rings programmatically is not yet supported but may be in the future
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
selectedIndex - gets the selected index of the outer ring (setting may come soon)
selectedLevel - gets the index of the level with the latest selection - the core is 0
selectedMenu - gets a reference to the selected menu
outerLevel - gets the index number of the outside level - the core is 0
outerMenu - gets a reference to the outer menu
text - gets current selected label text
label - gets current selected label object
selected - gets the selected button
core - a reference to the core circle object
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
enabled - default is true - set to false to disable
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
OPTIMIZED
This component is affected by the general OPTIMIZE setting (default is false)
if set to true, you will have to stage.update() after setting certain properties
and stage.update() in change event to see component change its graphics
ACTIONEVENT
This component is affected by the general ACTIONEVENT setting
The default is "mousedown" - if set to something else the component will act on click (press)
EVENTS
dispatches a "change" event when the button changes (but not when setting selectedIndex property)
see also selectedIndex, selectedLevel, selected and text properties
see also currentEnabled to get change event for each press - or use tap()
ALSO: See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+66.6
zim.RadialMenu = function(menu, size, font, height, coreRadius, coreColor, title, titleIcon, startAngle, totalAngle, flip, shiftRadial, rotateIcons, iconsShiftRadial, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, backdropColor, color, rollColor, selectedColor, selectedRollColor, borderColor, borderWidth, gradient, gap, gapAsAngle, spacing, spacingInner, spacingOuter, currentEnabled, currentSelected, open, under, style, group, inherit) {
var sig = "menu, size, font, height, coreRadius, coreColor, title, titleIcon, startAngle, totalAngle, flip, shiftRadial, rotateIcons, iconsShiftRadial, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, backdropColor, color, rollColor, selectedColor, selectedRollColor, borderColor, borderWidth, gradient, gap, gapAsAngle, spacing, spacingInner, spacingOuter, currentEnabled, currentSelected, open, under, style, group, inherit";
var sigList = sig.split(", ");
var duoTest = false;
if (menu && menu.constructor === {}.constructor) {
for (var i in menu) {
if (sigList.indexOf(i) >= 0) {
duoTest = true;
break;
}
}
}
if (menu && duoTest) {var duo; if (duo = zob(zim.RadialMenu, arguments, sig, this)) return duo;}
z_d("66.6");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "RadialMenu";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(menu)) menu = DS.menu!=null?DS.menu:{A:{A1:["AA1", "AA2", "AA3", "AA4"],A2:[],A3:[]},B:["B1","B2","B3","B4","B5","B6"],C:[]};
if (zot(size)) size = DS.size!=null?DS.size:30;
if (zot(font)) font = DS.font!=null?DS.font:"verdana";
if (zot(startAngle)) startAngle = DS.startAngle!=null?DS.startAngle:null; // top center
if (zot(totalAngle)) totalAngle = DS.totalAngle!=null?DS.totalAngle:360;
if (zot(flip)) flip = DS.flip!=null?DS.flip:true;
if (zot(rotateIcons)) rotateIcons = DS.rotateIcons!=null?DS.rotateIcons:false;
if (zot(shiftRadial)) shiftRadial = DS.shiftRadial!=null?DS.shiftRadial:0;
if (zot(iconsShiftRadial)) iconsShiftRadial = DS.iconsShiftRadial!=null?DS.iconsShiftRadial:0;
if (zot(height)) height = DS.height!=null?DS.height:60;
if (zot(coreRadius)) coreRadius = DS.coreRadius!=null?DS.coreRadius:100;
if (zot(coreColor)) coreColor = DS.coreColor!=null?DS.coreColor:"#333";
if (zot(title)) title = DS.title!=null?DS.title:"MENU";
if (zot(titleIcon)) titleIcon = DS.titleIcon!=null?DS.titleIcon:null;
if (zot(backdropColor)) backdropColor = DS.backdropColor!=null?DS.backdropColor:zim.clear;
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"#666";
if (zot(rollBackgroundColor)) rollBackgroundColor = DS.rollBackgroundColor!=null?DS.rollBackgroundColor:"#777";
if (zot(selectedBackgroundColor)) selectedBackgroundColor = DS.selectedBackgroundColor!=null?DS.selectedBackgroundColor:"#444";
if (zot(selectedRollBackgroundColor)) selectedRollBackgroundColor = DS.selectedRollBackgroundColor!=null?DS.selectedRollBackgroundColor:selectedBackgroundColor;
if (zot(color)) color = DS.color!=null?DS.color:"white";
if (zot(rollColor)) rollColor = DS.rollColor!=null?DS.rollColor:color;
if (zot(selectedColor)) selectedColor = DS.selectedColor!=null?DS.selectedColor:color;
if (zot(selectedRollColor)) selectedRollColor = DS.selectedRollColor!=null?DS.selectedRollColor:rollColor;
if (zot(borderColor)) borderColor=DS.borderColor!=null?DS.borderColor:"#333";
if (zot(borderWidth)) borderWidth=DS.borderWidth!=null?DS.borderWidth:2; // 0
if (zot(gapAsAngle)) gapAsAngle=DS.gapAsAngle!=null?DS.gapAsAngle:false;
if (zot(gap)) gap=DS.gap!=null?DS.gap:(gapAsAngle?3:6);
if (zot(spacing)) spacing=DS.spacing!=null?DS.spacing:6;
if (zot(gradient)) gradient=DS.gradient!=null?DS.gradient:null;
if (gradient === true) gradient = .1;
if (zot(spacingInner)) spacingInner=DS.spacingInner!=null?DS.spacingInner:spacing;
if (zot(spacingOuter)) spacingOuter=DS.spacingOuter!=null?DS.spacingOuter:spacing;
if (zot(currentEnabled)) currentEnabled=DS.currentEnabled!=null?DS.currentEnabled:false;
if (zot(currentSelected)) currentSelected=DS.currentSelected!=null?DS.currentSelected:true;
if (zot(open)) open=DS.open!=null?DS.open:false;
if (zot(under)) under=DS.under!=null?DS.under:true;
var that = this;
var eventType = (!zns?ACTIONEVENT=="mousedown":zim.ACTIONEVENT=="mousedown")?"mousedown":"click"
var lastSelected = null;
var core = this.core = new Circle(coreRadius, coreColor).addTo(this);
if (titleIcon) this.titleIcon = titleIcon.center(core);
if (title) this.title = new Label(title, size, font, color).center(core);
core.cursor = "pointer";
core.on(eventType, function(e) {
that.leafNode = false;
if (radials.length == 0) {
changeRadial();
} else {
loop(radials, function (radial) {
radial.selectedIndex = -1;
radial.removeFrom();
radials = [];
});
that.outerLevel = 0;
that.selected = that.outerMenu = that.selectedMenu = that.text = null;
}
if (currentEnabled || that.selected != lastSelected) that.dispatchEvent("change");
lastSelected = that.selected;
if (that.stage) that.stage.update();
});
this.closeRings = function(num) {
if (zot(num)) num = that.outerLevel;
var lev = that.outerLevel - num;
loop(radials, function (radial, i) {
if (i>lev-1) {
radial.removeFrom();
radial.selectedIndex = -1;
radials.pop();
}
}, true); // loop backwards
that.outerLevel = lev;
that.outerMenu = radials[radials.length-1];
if (that.outerMenu) that.outerMenu.selectedIndex = -1;
that.selected = that.selectedMenu = that.text = null;
if (radials[radials.length-2]) {
that.selectedMenu = radials[radials.length-2];
that.selectedIndex = that.selectedMenu.selectedIndex;
}
else that.selectedIndex = -1;
if (that.selected != lastSelected) that.dispatchEvent("change");
lastSelected = that.selected;
if (that.stage) that.stage.update();
}
// handle menu data
var menus = {}; // holds created menus and does not remove them
var tree;
var ids;
that.outerLevel = 0;
if (menu.constructor == {}.constructor) {
menu = {core:menu};
tree = that.tree = new zim.Hierarchy(menu);
ids = tree.getLinearIDs();
}
that.lastRadial = null;
var radials = this.radials = [];
if (open) {changeRadial();}
function changeRadial(currentRadial) {
var level, radius;
if (!currentRadial) { // from core
level = 0;
radius = coreRadius;
} else {
// figure out the level based on currentRadial
level = currentRadial.level;
}
// remove previous outer selections
loop(radials, function (radial, i) {
if (i>level-1) {
radial.removeFrom();
radial.selectedIndex = -1;
radials.pop();
}
}, true); // loop backwards
var currentButton;
if (currentRadial) currentButton = currentRadial.selected;
if (currentButton) {
id = currentButton.id;
radius = currentRadial.outerRadius;
makeRadial(id, level+1, radius);
} else if (!currentRadial) {
makeRadial("id0", level+1, radius);
} // else turning off button on current radial
that.selected = currentButton;
if (that.selected) {
that.selectedMenu = radials[that.selected.menu.level-1];
that.selectedIndex = that.selected.num;
if (that.selected.label) that.text = that.selected.label.text;
else that.text = null;
} else {
if (currentEnabled && currentRadial) {
that.selectedIndex = currentRadial.selectedIndex;
that.label = currentRadial.label;
that.text = currentRadial.text;
that.icon = currentRadial.icon;
that.selectedMenu = currentRadial;
} else {
that.text = null;
that.selectedIndex = -1;
that.selectedMenu = null;
}
}
if (that.stage) that.stage.update();
};
function makeRadial(id, level, radius) {
if (level) that.outerLevel = level;
var currentMenu;
if (!menus[id]) {
var data = tree.getData(id);
var list = data.list;
if (list && !zim.isEmpty(list)) {
var props = {
labels:tree.getLinearList(list),
coreRadius:radius,
size:size,
font:font,
startAngle:startAngle,
totalAngle:totalAngle,
flip:flip,
rotateIcons:rotateIcons,
shiftRadial:shiftRadial,
iconsShiftRadial:iconsShiftRadial,
height:height,
coreColor:clear,
backdropColor:backdropColor,
backgroundColor:backgroundColor,
rollBackgroundColor:rollBackgroundColor,
selectedBackgroundColor:selectedBackgroundColor,
selectedRollBackgroundColor:selectedRollBackgroundColor,
color:color,
rollColor:rollColor,
selectedColor:selectedColor,
selectedRollColor:selectedRollColor,
borderColor:borderColor,
borderWidth:borderWidth,
gapAsAngle:gapAsAngle,
gap:gap,
gradient:gradient,
spacingInner:spacingInner,
spacingOuter:spacingOuter,
currentSelected:currentSelected,
currentEnabled:currentEnabled
}
var obj = tree
if (data.styles) {
props = merge(props, data.styles);
}
currentMenu = menus[id] = new Radial(props);
ids = tree.getLinearIDs(list);
currentMenu.buttons.loop(function (button, i) {
button.menu = currentMenu;
button.id = ids[i];
});
currentMenu.level = that.outerLevel;
currentMenu.on("change", function(e) {
that.leafNode = false;
changeRadial(e.target);
if (currentEnabled || that.selected != lastSelected) that.dispatchEvent("change");
lastSelected = that.selected;
});
}
}
if (menus[id]) {
radials.push(menus[id]);
menus[id].center(that);
if (under) menus[id].bot();
} else {
that.leafNode = true;
that.outerLevel -= 1;
}
that.outerMenu = currentMenu;
}
zimStyleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.RadialMenu(menu, size, font, height, coreRadius, coreColor, title, titleIcon, startAngle, totalAngle, flip, shiftRadial, rotateIcons, iconsShiftRadial, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, backdropColor, color, rollColor, selectedColor, selectedRollColor, borderColor, borderWidth, gradient, gap, gapAsAngle, spacing, spacingInner, spacingOuter, currentEnabled, currentSelected, open, under, style, this.group, inherit));
}
}
zim.extend(zim.RadialMenu, zim.Container, "clone", "zimContainer", false);
//-66.6
/*--
zim.ColorPicker = function(width, colors, cols, spacing, greyPicker, alphaPicker, startBackgroundColor, draggable, shadowColor, shadowBlur, buttonBar, circles, indicator, backgroundColor, keyArrows, container, selectedIndex, style, group, inherit)
ColorPicker
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
A traditional color picker which shows 256 Web colors by default or custom colors.
Can additionally show 16 greys and / or an alpha slider.
Picking on a color sets the swatch color and the selectedColor property.
OK dispatches a "change" event if the color changed or a close event if not.
The X dispatches a "close" event.
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var cp = new ColorPicker();
cp.center(stage);
cp.on("change", function() {
zog(cp.selectedColor); // #ffcc99, etc. after pressing OK
zog(cp.selectedAlpha); // 0-1
});
stage.update();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - (default 500) the width of the color picker
colors - (default 256 Web colors) an optional list of colors ["red", "#CCC", etc.]
cols - (default 10) how many columns to use if you pass in custom colors
spacing - (default 2) is the space between the color squares
greyPicker - (default true unless one row) shows an extra 16 greys (set to false to hide these)
for the default colors it also includes 2 starting colors that record last picked colors
alphaPicker - (default true unless one row) shows an alpha slider (set to false to hide this)
the swatch has a black, grey and white backing underneath to show multiple alpha effects
startBackgroundColor - (default the last color in color array) the starting color
draggable - (default true (false if no buttonBar)) whether you can drag the component - set to false to not drag
a small grip under the color text shows if draggable
shadowColor - (default rgba(0,0,0,.3)) set to -1 for no drop shadow
shadowBlur - (default 14) the blur of the shadow if shadow is set
buttonBar - (default true unless one row) set to false to hide the button bar with OK and X (close)
circles - (default false) set to true to show colors in circles rather than squares
indicator - (default true) set to false to remove indicator from currentBackgroundColor
backgroundColor - (default black) the color of the background
keyArrows - (default true) set to false to disable keyboard arrows
container - (default frame.zimDefaultFrame) if using show(), hide(), toggle() can set which container to center on
selectedIndex - (default 0) - set the selectedIndex at start
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
show() - show the picker (returns the picker for chaining)
hide() - hides the picker
toggle(state - default null) - shows if hidden and hides if showing (returns the picker for chaining)
or pass in true to show picker or false to hide picker
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
selectedColor - gets or sets the selected color swatch
currentValue - same as selectedColor but consistent with other components
currentValueEvent - gets or sets the current value and dispatches a "change" event if set and changed
selectedAlpha - gets or sets the selected alpha (set does not work if alphaPicker is false)
selectedIndex - get or sets the selected index of the colorPicker
colors - read only array of colors in picker - not including greys
greys - read only array of greys in picker if the grey picker is set
toggled - read-only Boolean property as to whether picker is showing
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
swatch - gets the Rectangle that is the color swatch
swatchBacking - gets the zim Shape that is under the swatch (seen if alpha set low)
swatchText - gets the Label that shows the color text
grip - gets the createjs.Shape for the grip if the panel is dragable
background - gets the Rectangle that is the background (cp.background.color = "white" - now a backgroundColor parameter)
okBut - references the OK Button
closeBut - references the X Button
indicator - gets the zim shape that is the indicator (if indicator is true)
NOTE: alphaPicker is true:
alpaBacking - gets reference to the Rectangle that makes the backing for the alpha slider
alphaBut - the Button on the alpha slider
alphaSlider - the Slider for the alpha
alphaText - the Label for the alpha
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
keyFocus - get or set the keyboard focus on the component - see also zim.KEYFOCUS
will be set to true if this component is the first made or component is the last to be used
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
ACTIONEVENT
This component is affected by the general ACTIONEVENT setting
The default is "mousedown" - if set to something else the component will act on click (press)
EVENTS
dispatches a "set" event when a different color or alpha is selected and updated in the picker if the buttonBar is showing
dispatches a "change" event when the OK button is activated and the color or alpha is different than before
or if buttonBar is false dispatches "change" when a new color or alpha is selected
dispatches a "close" event if the OK button is activated and the color has not changed or the X button is pressed
ALSO: See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+67
zim.ColorPicker = function(width, colors, cols, spacing, greyPicker, alphaPicker, startBackgroundColor, draggable, shadowColor, shadowBlur, buttonBar, circles, indicator, backgroundColor, keyArrows, container, selectedIndex, style, group, inherit) {
var sig = "width, colors, cols, spacing, greyPicker, alphaPicker, startBackgroundColor, draggable, shadowColor, shadowBlur, buttonBar, circles, indicator, backgroundColor, keyArrows, container, selectedIndex, style, group, inherit";
var duo; if (duo = zob(zim.ColorPicker, arguments, sig, this)) return duo;
z_d("67");
this.zimContainer_constructor(null,null,null,null,false);
this.type = "ColorPicker";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(width)) width = DS.width!=null?DS.width:500;
if (zot(colors)) colors = DS.colors!=null?DS.colors:null;
if (zot(colors)) standard = true;
if (zot(cols)) cols = DS.cols!=null?DS.cols:10;
if (zot(spacing)) spacing = DS.spacing!=null?DS.spacing:2;
var oneRow = !standard&&colors.length>0&&colors.length<=cols;
if (zot(alphaPicker)) alphaPicker = DS.alphaPicker!=null?DS.alphaPicker:(oneRow?false:true);
if (zot(greyPicker)) greyPicker = DS.greyPicker!=null?DS.greyPicker:(oneRow?false:true);
if (zot(shadowColor)) shadowColor = DS.shadowColor!=null?DS.shadowColor:"rgba(0,0,0,.3)";
if (zot(shadowBlur)) shadowBlur = DS.shadowBlur!=null?DS.shadowBlur:14;
if (zot(buttonBar)) buttonBar = DS.buttonBar!=null?DS.buttonBar:(oneRow?false:true);
if (zot(draggable)) {
if (buttonBar) {
draggable = DS.draggable!=null?DS.draggable:true;
} else {
draggable = DS.draggable!=null?DS.draggable:false;
}
}
if (zot(circles)) circles = DS.circles!=null?DS.circles:false;
if (zot(indicator)) {
indicator = DS.indicator!=null?DS.indicator:false;
if (!buttonBar) indicator = DS.indicator!=null?DS.indicator:true;
}
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"black";
if (zot(startBackgroundColor)) startBackgroundColor = DS.startBackgroundColor!=null?DS.startBackgroundColor:null;
if (zot(keyArrows)) keyArrows = DS.keyArrows!=null?DS.keyArrows:true;
var that = this;
var stage;
if (zot(container)) {
if (zimDefaultFrame) container = zimDefaultFrame.stage;
else return;
} else if (!container.getBounds) {
return;
} else if (zot(container.getStage)) {
return;
}
that.container = container;
var secondLastBackgroundColor = "#e472c4"; // only used on standard colors
var thirdLastBackgroundColor = "#50c4b7";
var lastAlpha = 1;
var myAlpha = 1;
var box = new createjs.Shape(); // shape that holds all colors and greys
this.addChild(box);
box.x += spacing;
box.y += spacing;
var standard = false;
var colorsTemp; var w;
var greys = [];
if (zot(colors)) {
standard = true;
var num = 6; // six sets 0,3,6,9,C,F - for Web colors
var tot = num*num*num;
num = Math.ceil(Math.pow(tot,1/2));
w = (width - spacing)/18-spacing;
var f = Math.floor(Math.pow(num*num, 1/3));
colorsTemp = [];
for (var i=0; i<6; i++) {
for (var j=0; j<6; j++) {
for (var k=0; k<6; k++) {
colorsTemp.push("#" + con(i*3) + con(j*3) + con(k*3));
}
}
}
colors = []; // flip every six by six sideways and put on two lines
var c, r, nC, nR;
for (i=0; i= 6*3) {f = 1;} else {f = 0;}
nC = c-f*6*3;
nR = r+f*6;
colors[nR*18+nC] = colorsTemp[i];
}
cols = 18;
greys = [thirdLastBackgroundColor, secondLastBackgroundColor];
} else {
w = (width - spacing) / cols - spacing;
}
var rows = Math.ceil(colors.length/cols);
var startAlpha = 1;
var myColor = String(colors[colors.length-1]);
if (!zot(startBackgroundColor)) {
var matches = startBackgroundColor.match(/rgba\((.*)\)/)
if (matches) {
var c = matches[1].split(",");
startAlpha = c.pop();
startBackgroundColor = "rgb("+c.join(",")+")";
}
myColor = String(startBackgroundColor);
}
var lastBackgroundColor;
if (standard) lastBackgroundColor = thirdLastBackgroundColor;
function con(n) {
n = Math.floor(n).toString(16);
return n + "" + n;
}
var g = box.graphics; var f=0; var color, r, c, rX , rY;
var borderColor = DS.borderColor!=null?DS.borderColor:null;
var borderWidth = DS.borderWidth!=null?DS.borderWidth:null;
if (!zot(borderColor) && zot(borderWidth)) borderWidth = 1;
if (borderWidth && zot(borderColor)) borderColor = "#333";
if (borderWidth) g.s(borderColor).ss(borderWidth);
for (i=0; i 0) background.shadow = new createjs.Shadow(shadowColor, 8, 8, shadowBlur);
function doChange(){
if (myColor != lastBackgroundColor || myAlpha != lastAlpha) {
if (standard && greyPicker) {
thirdLastBackgroundColor = secondLastBackgroundColor;
secondLastBackgroundColor = lastBackgroundColor;
var lastBackgroundColors = [thirdLastBackgroundColor, secondLastBackgroundColor]
for (i=0; i<2; i++) {
var g = box.graphics;
c = Math.floor(i/cols);
r = i%cols;
rX = r*(w+spacing);
rY = c*(w+spacing)+greyHeight;
greys[i] = lastBackgroundColors[i];
g.f(background.color).r(rX-1,rY-1,w+2,w+2).f(lastBackgroundColors[i]).r(rX,rY,w,w);
}
if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
lastBackgroundColor = myColor;
lastAlpha = myAlpha;
that.dispatchEvent("change");
} else {
that.dispatchEvent("close");
}
}
if (draggable) {
var diffX, diffY;
background.on("mousedown", function(e) {
stage = e.target.stage;
diffX = e.stageX/zim.scaX - that.x;
diffY = e.stageY/zim.scaY - that.y;
background.cursor = "move";
});
background.on("pressmove", function(e) {
that.x = e.stageX/zim.scaX-diffX;
that.y = e.stageY/zim.scaY-diffY;
if (that.stage) that.stage.update();
});
background.on("pressup", function(e) {
background.cursor = "default";
if (that.stage) that.stage.update();
});
}
var gridW = cols*(w+spacing);
var gridH = rows*(w+spacing);
if (greyPicker) {
var greyW = greyCols*(w+spacing);
var greyH = greyRows*(w+spacing);
}
box.on((!zns?ACTIONEVENT=="mousedown":zim.ACTIONEVENT=="mousedown")?"mousedown":"click", function(e) {
var index = zim.hitTestGrid(box, gridW, gridH, cols, rows, e.stageX, e.stageY, 0, 0, spacing, spacing);
if (!zot(index)) {
myColor = colors[index];
if (buttonBar) {
swatch.color = myColor;
swatchText.text = String(colors[index]).toUpperCase();
if (myColor != lastBackgroundColor) that.dispatchEvent("set");
} else {
doChange();
}
}
if (greyPicker) {
// note greyW not gridW
index = null;
index = zim.hitTestGrid(box, greyW, greyH, greyCols, greyRows, e.stageX, e.stageY, 0, gridH, spacing, spacing);
if (!zot(index)) {
myColor = greys[index];
if (buttonBar) {
swatch.color = myColor;
swatchText.text = greys[index].toUpperCase();
if (myColor != lastBackgroundColor) that.dispatchEvent("set");
} else {
doChange();
}
}
}
if (indicator) positionIndicator(colors.indexOf(myColor));
if (buttonBar) {
if (that.stage) that.stage.update();
} else if (indicator) {
if (that.stage) that.stage.update();
// if ((!zim.OPTIMIZE&&(zns||!OPTIMIZE)) && that.stage) that.stage.update();
}
setAccessibility();
});
Object.defineProperty(this, 'selectedColor', {
get: function() {
return myColor;
},
set: function(value) {
value = value.toUpperCase();
lastBackgroundColor = myColor = value;
if (buttonBar) {
swatch.color = myColor;
swatchText.text = myColor;
if (that.stage) that.stage.update();
}
if (indicator) positionIndicator(colors.indexOf(myColor));
setAccessibility();
}
});
Object.defineProperty(this, 'currentValue', { // alternate to selectedColor
get: function() {
return myColor;
},
set: function(value) {
that.selectedColor = value;
}
});
Object.defineProperty(this, 'currentValueEvent', { // currentValue and also triggers change event
get: function() {
return myColor;
},
set: function(value) {
if (value != that.selectedColor) {
that.selectedColor = value;
that.dispatchEvent("change");
}
}
});
Object.defineProperty(this, 'selectedIndex', {
get: function() {
return colors.indexOf(myColor);
},
set: function(value) {
lastBackgroundColor = myColor = colors[value];
if (buttonBar) {
swatch.color = myColor;
swatchText.text = myColor;
if (that.stage) that.stage.update();
}
if (indicator) positionIndicator(colors.indexOf(myColor));
setAccessibility();
}
});
Object.defineProperty(this, 'selectedAlpha', {
get: function() {
if (alphaPicker) {
return decimals(slider.currentValue);
} else {
return 1;
}
},
set: function(value) {
if (alphaPicker) {
lastAlpha = slider.currentValue = value;
if (swatch) swatch.alpha = lastAlpha;
if (alphaText) alphaText.text = "Alpha: " + decimals(slider.currentValue);
if (that.stage) that.stage.update();
}
}
});
Object.defineProperty(this, 'colors', {
get: function() {
if (greyPicker) return colors.concat(greys);
else return colors;
},
set: function(value) {
if (zon) zogy("ColorPicker() colors is read only - make a new ColorPicker to change")
}
});
if (typeof KEYFOCUS !== typeof undefined) zim.KEYFOCUS = KEYFOCUS;
Object.defineProperty(this, 'keyFocus', {
get: function() {
return zim.KEYFOCUS == that;
},
set: function(value) {
if (zns) zim.KEYFOCUS = that;
else KEYFOCUS = that;
}
});
if (keyArrows && zim.KEYFOCUS) setFocus();
this.on("mousedown", function() {if (keyArrows) setFocus()});
function setFocus() {that.keyFocus = true; var d=document.activeElement; if (d) d.blur();}
function setAccessibility() {
if (that.zimAccessibility) that.zimAccessibility.changeTitle(that, null, true);
}
this.keyDownEvent = function(e) {
if (!that.stage) return;
if ((that.zimAccessibility && that.focus) || (!that.zimAccessibility && that.keyFocus)) {
var currentTemp = that.selectedIndex;
if (e.keyCode == 37 || e.keyCode == 40) {
currentTemp--;
changeMe();
} else if (e.keyCode == 38 || e.keyCode == 39){
currentTemp++;
changeMe();
}
function changeMe() {
if (currentTemp < 0) currentTemp = that.colors.length-1;
if (currentTemp > that.colors.length-1) currentTemp = 0;
that.selectedIndex = currentTemp;
that.dispatchEvent("change");
if (that.stage) that.stage.update();
}
}
}
window.addEventListener("keydown", this.keyDownEvent);
this.hide = function() {
that.removeFrom();
that.toggled = false;
if (that.zimAccessibility) {
var a = that.zimAccessibility;
a.resize(that);
if (accessibilityClicker) accessibilityClicker.focus();
else that.zimTabTag.nextSibling.focus();
setTimeout(function() {a.talk("ColorPicker has been closed.");}, 50);
}
return that;
}
var accessibilityClicker;
this.show = function() {
that.center(that.container);
if (that.zimAccessibility) {
var a = that.zimAccessibility;
setTimeout(function(){if (a.activatedObject) accessibilityClicker = a.activatedObject.zimTabTag;}, 50);
a.resize(that);
a.tabIndex = that.zimTabIndex;
}
that.toggled = true;
return that;
}
this.toggle = function(state) {
if (state===true) that.show();
else if (state===false) that.hide();
else if (that.container.contains(that)) that.hide();
else that.show();
return that;
}
function decimals(n) {
return Math.round(n*Math.pow(10, 2))/Math.pow(10, 2);
}
if (zot(selectedIndex)) selectedIndex=DS.selectedIndex!=null?DS.selectedIndex:0;
that.selectedIndex = selectedIndex;
if (style!==false) zimStyleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.ColorPicker(width, standard?null:colors, cols, spacing, greyPicker, alphaPicker, startBackgroundColor, draggable, shadowColor, shadowBlur, buttonBar, circles, indicator, backgroundColor, keyArrows, container, selectedIndex, style, this.group, inherit));
}
this.dispose = function(a,b,disposing) {
window.removeEventListener("keydown", that.keyDownEvent);
if (slider) slider.dispose();
if (!disposing) this.zimContainer_dispose(true);;
return true;
}
}
zim.extend(zim.ColorPicker, zim.Container, ["clone", "dispose"], "zimContainer", false);
//-67
/*--
zim.Keyboard = function(labels, backgroundColor, color, shiftBackgroundColor, shiftHoldBackgroundColor, placeBackgroundColor, placeColor, cursorColor, shadeAlpha, borderColor, borderWidth, margin, corner, draggable, placeClose, shadowColor, shadowBlur, container, data, place, special, rtl, hardKeyboard, style, group, inherit)
Keyboard
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
The Keyboard class makes a keyboard ideal for mobile or touch screens.
Often, it seems the mobile keyboard can cause problems with layout.
This in-canvas keyboard requires much less testing and concern.
The Keyboard can work with ZIM Labels to give input text without a TextArea.
Thanks Frank Los for the initial design and coding of the Keyboard.
Keyboard also captures hard keyboard keydown and will type that as well
See https://zimjs.com/keyboard
NOTE: press and hold down the vowels for multiple vowel options
NOTE: currently, multi-line Label input is not supported
NOTE: the width of the Label can be set by the Label's lineWidth paremeter
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
// create Labels to capture the text from the keyboard
var text1 = new Label({text:"", backgroundColor:white}).pos(100,100);
var text2 = new Label({text:"", backgroundColor:white}).pos(100,200);
// create a new Keyboard and pass in the labels as an array
// or if just one label, then pass in the label
var keyboard = new Keyboard([text1, text2]);
// if just the letter is needed use the keydown event
keyboard.on("keydown", function(e) {
zog(e.letter);
});
// create events to capture a mousedown on the labels
var text1Event = text1.on("mousedown", activate);
var text2Event = text2.on("mousedown", activate);
function activate(e) {
keyboard.show();
// remove the events when keyboard is active
text1.off("mousedown", text1Event);
text2.off("mousedown", text2Event);
}
keyboard.show(); // optionally show the keyboard to start
// add back the events to show the keyboard
keyboard.on("close", function() {
text1.on("mousedown", text1Event);
text2.on("mousedown", text2Event);
});
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
labels - (default null) a ZIM Label to show letters in or an array of labels
Keyboard will add a cursor to the Labels
and provide management across multiple labels
currently, multiline labels are not supported
setting the label lineWidth will set the max width of the label
backgroundColor - (default "#333") an css color for the background color of the keys
color - (default "white") the color of the text
shiftBackgroundColor - (default "orange") the color of the active shift key
shiftHoldBackgroundColor - (default "red") the color of the active shift hold key
placeBackgroundColor - (default "50c4b7") the color of the arrow backings when placing cursor in label
placeColor - (default "50c4b7") the color of the arrow text when placing cursor in label
cursorColor - (default "50c4b7") the cursor color
shadeAlpha - (default .2) special keys are shaded darker by this alpha
margin - (default 5) the margin around the keyboard from the container width
corner - (default 30) the round of the corner (set to 0 for no corner)
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
draggable - (default false) set to true to show the drag handle at top right
placeClose - (default true) shows an x key to close the cursor placement menu
shadowColor - (default "rgba(0,0,0,.2)") set to -1 for no shadow
shadowBlur - (default 14) how blurred the shadow is if the shadow is set
container - (default zimCurrentFrame stage) if placing Keyboard in different container or stage
data - (default see below) pass in data for the letters on the three sets of keyboards
Below is the default data - change any of the keys to change keyboard
There must be three boards (you can request more)
There must be a button specified on the fourth row to toggle to the second screen and back
There must be a button on the second and third screen at the start of the third row
to toggle between the second and third screen
The "shift" and "delete" keys are optional and can be moved or removed
Where 10 keys can fit, there is a maximum of 10 keys but there can be less
Use the data property to get this array if desired:
var data = [
[
["q","w","e","r","t","y","u","i","o","p"],
["a","s","d","f","g","h","j","k","l"],
["shift","z","x","c","v","b","n","m","backspace"],
["?123"] // rest of bottom line automatically added
],[
["1","2","3","4","5","6","7","8","9","0"],
["!","@","#","$","/","^","&","*","(",")"],
["1/2","-","'", "\"",":",";",",","?","backspace"],
["ABC"] // rest of bottom line automatically added
],[
["+","x","%","=","<",">","{","}","[","]"],
["€","£","¥", "$", "₩", "~", "`","¤","♡","☆"],
["2/2","_","\\","|","《","》","¡","¿","backspace"],
["ABC"] // rest of bottom line automatically added
]
];
place (default true) - set to false to not add place arrows when selecting Label
special (default null) - set to a string to add a special key to the left of the space bar
rtl (default false) - (Experimental) set to true to use right-to-left text
hardKeyboard (default true) - set to false to not include keypresses from physical keyboard
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
show(index) - shows the Keyboard - use this rather than addTo(), etc.
index (default null) specify the index of the labels array to show cursor in
hide() - hides the keyboard
toggle(state - default null) - shows if hidden and hides if showing (returns the keyboard for chaining)
or pass in true to show keyboard or false to hide keyboard
addChar(char) - add a character to the currentLabel at the currentIndex
removeChar() - removes the chararcter in the currentLabel at the currentIndex-1 (a backspace)
addLabels(labels) - add a ZIM Label or an array of Labels to the labels list for the Keyboard
removeLabels(labels) - remove a ZIM Label or an array of Labels
showPlace() - show the place menu for cursor
hidePlace() - hide the place menu for cursor
resize() - scales the keyboard to the stage with margin and places at bottom of screen
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a clone of the Keyboard
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
data - get the data array for the keyboard - see the data parameter for details and to set value for data
labels - get the labels array - use addLabels() and removeLabels() to set
selectedLabel - the label with the cursor or -1 if no cursor
selectedIndex - the index of the cursor in the selected label or -1 if no cursor
type - holds the class name as a String
toggled - read-only Boolean that is true if keyboard is visible and false if not
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
Dispatches a "keydown" event with an event object having a letter property
keyboard.on("keydown", function(e) {zog(e.letter);}); // logs letter pressed or "del" for delete
Dispatches a "special" event if the special parameter is used and the special key is pressed
Dispatches a "close" event when close keyboard icon at bottom right is pressed
ALSO: See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+67.2
zim.Keyboard = function(labels, backgroundColor, color, shiftBackgroundColor, shiftHoldBackgroundColor, placeBackgroundColor, placeColor, cursorColor, shadeAlpha, borderColor, borderWidth, margin, corner, draggable, placeClose, shadowColor, shadowBlur, container, data, place, special, rtl, hardKeyboard, style, group, inherit) {
var sig = "labels, backgroundColor, color, shiftBackgroundColor, shiftHoldBackgroundColor, placeBackgroundColor, placeColor, cursorColor, shadeAlpha, borderColor, borderWidth, margin, corner, draggable, placeClose, shadowColor, shadowBlur, container, data, place, special, rtl, hardKeyboard, style, group, inherit";
var duo; if (duo = zob(zim.Keyboard, arguments, sig, this)) return duo;
z_d("67.2");
this.zimContainer_constructor(1000,400,null,null,false);
this.type = "Keyboard";
this.group = group;
var DS = style===false?{}:zim.getStyle(this.type, this.group, inherit);
if (zot(labels)) labels = DS.labels!=null?DS.labels:[];
if (!Array.isArray(labels)) labels = [labels];
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"#333";
if (zot(color)) color = DS.color!=null?DS.color:"white";
if (zot(shiftBackgroundColor)) shiftBackgroundColor = DS.shiftBackgroundColor!=null?DS.shiftBackgroundColor:"orange";
if (zot(shiftHoldBackgroundColor)) shiftHoldBackgroundColor = DS.shiftHoldBackgroundColor!=null?DS.shiftHoldBackgroundColor:"red";
if (zot(placeBackgroundColor)) placeBackgroundColor = DS.placeBackgroundColor!=null?DS.placeBackgroundColor:"#50c4b7";
if (zot(placeColor)) placeColor = DS.placeColor!=null?DS.placeColor:color;
if (zot(cursorColor)) cursorColor = DS.cursorColor!=null?DS.cursorColor:"#50c4b7";
if (zot(shadeAlpha)) shadeAlpha = DS.shadeAlpha!=null?DS.shadeAlpha:.2;
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:"rgba(0,0,0,.1)";
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:null;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = 1;
if (zot(margin)) margin = DS.margin!=null?DS.margin:5;
if (zot(corner)) corner = DS.corner!=null?DS.corner:30;
if (zot(draggable)) draggable = DS.draggable!=null?DS.draggable:false;
if (zot(placeClose)) placeClose = DS.placeClose!=null?DS.placeClose:true;
if (zot(shadowColor)) shadowColor=DS.shadowColor!=null?DS.shadowColor:"rgba(0,0,0,.2)";
if (zot(shadowBlur)) shadowBlur=DS.shadowBlur!=null?DS.shadowBlur:14;
if (zot(data)) data = DS.data!=null?DS.data:[
[
["q","w","e","r","t","y","u","i","o","p"],
["a","s","d","f","g","h","j","k","l"],
["shift","z","x","c","v","b","n","m","backspace"],
["?123"] // rest of bottom line automatically added
],[
["1","2","3","4","5","6","7","8","9","0"],
["!","@","#","$","/","^","&","*","(",")"],
["1/2","-","'", "\"",":",";",",","?","backspace"],
["ABC"] // rest of bottom line automatically added
],[
["+","x","%","=","<",">","{","}","[","]"],
["€","£","¥", "$", "₩", "~", "`","¤","♡","☆"],
["2/2","_","\\","|","《","》","¡","¿","backspace"],
["ABC"] // rest of bottom line automatically added
]
];
var that = this;
that.data = data;
if (zot(place)) place = DS.place!=null?DS.place:true;
if (zot(rtl)) rtl = DS.rtl!=null?DS.rtl:false;
if (zot(hardKeyboard)) hardKeyboard = DS.hardKeyboard!=null?DS.hardKeyboard:true;
var mess = "zim display - Keyboard(): Please pass in a reference to a container with bounds set";
if (zot(container)) {
if (zimDefaultFrame) {
container = zimDefaultFrame.stage;
} else {
zog(mess);
return;
}
} else if (!container.getBounds) {
zog(mess);
return;
} else if (zot(container.stage)) {
zog("zim display - Keyboard(): The container must have a stage property");
return;
}
if (shadowColor != -1 && shadowBlur > 0) that.shadow = new createjs.Shadow(shadowColor, 3, 3, shadowBlur);
var currentStage = zimDefaultFrame?zimDefaultFrame.stage:null;
// ~~~~~~~~~~~~~~~~~ SETUP
that.labels = labels;
var maxWidth;
var numH = 10;
var botArray = ["@","",".","/","away"];
if (!zot(special)) botArray.splice(1,0,special);
var textKeys = zim.copy(data[0]);
// textKeys[2].unshift("shift");
// textKeys[2].push("backspace");
textKeys[3] = textKeys[3].concat(botArray);
var numberKeys1 = zim.copy(data[1]);
// numberKeys1[2].push("backspace");
numberKeys1[3] = numberKeys1[3].concat(botArray);
var numberKeys2 = zim.copy(data[2]);
// numberKeys2[2].push("backspace");
numberKeys2[3] = numberKeys2[3].concat(botArray);
// var textKeys = [
// ["q","w","e","r","t","y","u","i","o","p"],
// ["a","s","d","f","g","h","j","k","l"],
// ["shift","z","x","c","v","b","n","m","backspace"],
// ["?123","@","",".","/","away"]
// ]
// var numberKeys1 = [
// ["1","2","3","4","5","6","7","8","9","0"],
// ["!","@","#","$","/","^","&","*","(",")"],
// ["1/2","-","'", "\"",":",";",",","?","backspace"],
// ["ABC","@","",".","/","away"]
// ];
// var numberKeys2 = [
// ["+","x","%","=","<",">","{","}","[","]"],
// ["€","£","¥", "$", "₩", "~", "`","¤","♡","☆"],
// ["2/2","_","\\","|","《","》","¡","¿","backspace"],
// ["ABC", "@","",".","/","away"]
// ];
var eLetters = ["ė","ē","ę","ê","é","ë","è"];//ĒĘÊÉËÈ
var uLetters = ["ū","û","ú","ü","ù"];//ŪÛÚÜÙ
var iLetters = ["ī","į","ì","í","ï","î"];//ĪĮÌÍÏÎ
var oLetters = ["ō","œ","ø","õ","ô","ó","ö","ò"];// ŌŒØÕÔÓÖÒ
var aLetters = ["ā","ã","å","â","á","ä","à","æ"];// ĀÃÅÂÁÄÀÆ
var nLetters = ["ñ","ń"];
var textKeyButtons = [];
//maateenheid horizontaal
var size = (1000-(9*5))/numH;
//statuses toestenbord
var statuses = {
def:"default",
shift:"shift",
number1:"number1",
number2:"number2"
};
var currentStatus = statuses.def;
var currentKeyboard;
var alternativeMenu;
var textBlinker;
var bigShiftOn = false;
var shiftKey;
var currentLabel;
var insertPoint = 0;
var cursorShiftMenu;
var buttonsCursor = [];
var shiftKeyIcon;
var backspaceIcon;
var hideKeyBoardIcon;
var dragButton;
var dragY;
makeIcons();
makeButtons(currentStatus);
if (draggable) makeDragButton();
// ~~~~~~~~~~~~~~~~~ INTERACTIONS
this.on("mousedown", buttonPressed);
function buttonPressed(e) {
currentStage = that.stage;
if (alternativeMenu) {
that.removeChild(alternativeMenu);
}
if (cursorShiftMenu) {
if (buttonsCursor.indexOf (e.target) < 0) {
removeCursorShiftMenu();
}
}
if (!zot(e.target.name)) {
//WIJZIGINGEN STATUS keyboard
if (draggable && e.target === dragButton) {
that.tickerMouseEvent = currentStage.on("stagemousemove", function(e) {
that.mouseYAmount = e.stageY;
});
zim.Ticker.add(startDragging);
that.on("pressup", stopDragging);
dragY = e.stageY-that.localToGlobal(0,0).y;
} else if (!zot(special) && e.target.name === special) {
that.dispatchEvent("special");
} else if (e.target.name === "shift") { //shift
shiftKeys();
} else if (e.target.toggle === "?123") { //nummers
that.removeChild(currentKeyboard);
makeButtons(statuses.number1);
} else if (e.target.toggle === "ABC") { //teksten
that.removeChild(currentKeyboard);
currentStatus = statuses.def;
makeButtons();
if (bigShiftOn) shiftKeys(true);
} else if (e.target.toggle==="1/2") {
that.removeChild(currentKeyboard);
makeButtons(statuses.number2);
} else if (e.target.toggle==="2/2") {
that.removeChild(currentKeyboard);
makeButtons(statuses.number1);
} else if (e.target.name==="away") {
hideKeyboard();
that.dispatchEvent("close");
} else if (e.target.name === "e"||
e.target.name === "u"||
e.target.name === "i"||
e.target.name === "o"||
e.target.name === "a"||
e.target.name === "n") { //VARIATIES LETTERS euioan
makeAlternativeLetters(e.target.name);
} else if (e.target.name === "return") {
addToLabel("\n");
} else if (e.target.name === "backspace") {
backspaceRemovesLetter();
} else if (e.target.name === "") {
addToLabel(" ");
} else {
addToLabel(e.target.name);
}
currentStage.update();
}
}
that.addChar = function(char) {
if (!zot(char) && char.match(/^.$/)) addToLabel(char);
}
that.removeChar = function() {
backspaceRemovesLetter(true);
}
var shiftEvent;
function shiftKeys(immediate) {
var bigShift = false;
var i;
//vanuit default
if (currentStatus === statuses.def) {
shiftKey.color = immediate?shiftHoldBackgroundColor:shiftBackgroundColor;
//keyboard veranderen
for(i=0; i 0) {
if (tkb.name.length===1) {
tkb.label.text = tkb.label.text.toUpperCase();
tkb.label.centerReg(tkb).mov(0,6);
} else {
tkb.label.centerReg(tkb);
}
}
}
if (!immediate) {
//na halve seconde gaat groot shift aan
bigShift = true;
zim.timeout(500, putBigShiftOn);
shiftEvent = that.on("pressup", doNotPutBigShiftOn);
}
currentStatus = statuses.shift;
//vanuit shift
} else {
shiftKey.color = backgroundColor;
bigShiftOn = false;
//keyboard veranderen
for(i=0; i0) {
if (tkb.name.length===1) {
tkb.label.text = tkb.label.text.toLowerCase();
tkb.label.centerReg(tkb).mov(0,3);
} else {
tkb.label.centerReg(tkb);
}
}
}
currentStatus = statuses.def;
}
currentKeyboard.updateCache();
that.stage.update();
function putBigShiftOn() {
if (bigShift) {
bigShiftOn = true;
shiftKey.color = shiftHoldBackgroundColor;
currentKeyboard.updateCache();
that.stage.update();
}
}
function doNotPutBigShiftOn(e) {
that.off("pressup", shiftEvent);
bigShift = false;
}
}
// ~~~~~~~~~~~~~~~~~ ASSETS
function makeButtons(which) {
var typeKeyboard;
var label;
var button;
var bakking;
var xPos = 0;
var yPos = 0;
var thisWidth;
var bigKey;
var thisIsSpacekey= false;
var thisKeyLetter;
var passesLetter;
var dark= false;
//zonder parameters maak ik letters
if (zot(which)) which = statuses.def;
//letters
if (which === statuses.def) {
typeKeyboard = textKeys;
//nummers1
} else if (which === statuses.number1) {
typeKeyboard = numberKeys1;
//nummers 2
} else if (which === statuses.number2) {
typeKeyboard = numberKeys2;
}
//container maken
currentKeyboard = new zim.Container(1000,430,null,null,false).addTo(that);
//alle toetsen, door arrays heen wandelen
for (var i = 0; i","x"]:["<",">"];
var label;
var bakking;
var button;
var point;
buttonsCursor = [];
point = currentLabel.localToLocal(0, 0, that);
cursorShiftMenu = new zim.Container({style:false}).addTo(that).loc({x:point.x, y:point.y+currentLabel.height+15}).cur();
for (var i=0; i 0) insertPoint--;
} else if (buttonsCursor.indexOf(e.target)==1) {
if (insertPoint < currentLabel.text.length) insertPoint++;
} else {
removeCursorShiftMenu();
}
positionBlinker();
}
that.stage.update();
}
function removeCursorShiftMenu() {
if (!cursorShiftMenu) return that;
cursorShiftMenu.removeAllEventListeners();
that.removeChild(cursorShiftMenu);
cursorShiftMenu = null;
}
function addToLabel(letter) {
if (!currentLabel) return;
var measureField;
var widthMeasureField;
// backspace
if (letter === "del") {
if (currentLabel) currentLabel.text = [currentLabel.text.slice(0,insertPoint-1),currentLabel.text.slice(insertPoint)].join('');
insertPoint--;
makeWidthsArray();
} else {
if (currentStatus === statuses.shift) {
letter = letter.toUpperCase();
}
var textBeforeCheck = currentLabel.text;
measureField = currentLabel.clone().removeFrom();
measureField.text = letter;
widthMeasureField = measureField.label.getMeasuredWidth();
if (!currentLabel.widthArray) {
currentLabel.widthArray = [currentLabel.breedte];
} else {
currentLabel.widthArray.splice(insertPoint,0,widthMeasureField);
}
//toevoegen in string
if (insertPoint=0; i--) {
// sumUp += currentLabel.widthArray[i];
// if (point.x < sumUp-currentLabel.widthArray[i]/2) {
// insertPoint = i;
// found = true;
// break;
// }
// }
// var rightOfLabel = currentLabel.getBounds().width + currentLabel.getBounds().x;
// zog(rightOfLabel);
// zog(currentLabel.widthArray)
// for (var i=0; i 0) {
makeCursorShiftmenu();
}
if (cursorShiftMenu && currentLabel) {
if (currentLabel.text.length > 0) {
point = currentLabel.parent.localToLocal(currentLabel.x, currentLabel.y, that);
cursorShiftMenu.x = point.x;
cursorShiftMenu.y = point.y+currentLabel.height+15;
} else {
removeCursorShiftMenu();
}
}
}
function makeWidthsArray() {
if (!currentLabel) return;
var measureField;
currentLabel.widthArray = [];
for (var i=0; i0) {
if (that.selectedIndex > 0) addToLabel("del");
if (once) stopRemoval();
else that.on("pressup", stopRemoval);
} else {
addToLabel("del");
}
}
function stopRemoval() {
removalOkay = false;
if (timeOut) timeOut.clear();
that.off("pressup", stopRemoval);
}
removeLetter();
timeOut = zim.timeout(300, haalWeg);
that.stage.update();
}
function setLabels() {
for (var i=0; i 1) {
for (var i=0; i=0; i--) {
var ind = labels.indexOf(labs[i]);
if (ind >= 0 || labs[i].type != "Label") labs.splice(i, 1);
else labs[i].widthArray = [0];
}
unsetLabels();
labels = labels.concat(labs);
setLabels();
makeCursor();
if (textBlinker) textBlinker.visible = true;
return that;
}
this.removeLabels = function(labs) {
if (!Array.isArray(labs)) labs = [labs];
unsetLabels();
for (var i=0; i= 0) labels.splice(ind, 1);
}
setLabels();
if (labels.length == 0) {
if (currentLabel) removeCursor();
} else {
if (currentLabel && labels.indexOf(currentLabel) == -1) {
removeCursor();
makeCursor();
}
}
return that;
}
var background = new zim.Rectangle(this.width, this.height, zim.clear, null, null, null, null, null, false).addTo(this).expand().bot();
background.on("mousedown", function(){});
background.on("click", function(){});
this.resize = function() {
that.scaleTo(currentStage, 100-margin*2/currentStage.width*100, 50-margin*2/currentStage.height*100);
that.y = currentStage.height - that.height - margin;
that.x = currentStage.width/2 - that.width/2;
if (currentLabel && cursorShiftMenu) {
point = currentLabel.localToLocal(0, 0, that);
cursorShiftMenu.x = point.x;
cursorShiftMenu.y = point.y+currentLabel.height+15;
}
if (that.stage) that.stage.update();
return that;
}
this.resize();
if (that.selectedLabel) that.selectedIndex = that.selectedLabel.text.length;
// Dan Zen added ZIM 10.5.1
if (hardKeyboard) {
this.keydownEvent = window.addEventListener("keydown", function(e) {
if (!that.stage) return;
var k = that;
if (zot(k)) return;
if (e.keyCode==35) k.selectedIndex = k.selectedLabel.text.length; // end
if (e.keyCode==36) k.selectedIndex = 0; // home
if (e.keyCode==37) k.selectedIndex = k.selectedIndex-1; // left
if (e.keyCode==39) k.selectedIndex = k.selectedIndex+1; // right
if (e.keyCode==46) { // del
if (k.selectedIndex < k.selectedLabel.text.length) {
k.selectedIndex = k.selectedIndex + 1;
k.removeChar();
}
};
if (e.keyCode==8) {
e.preventDefault();
k.removeChar(); // backspace
}
k.addChar(e.key);
if (that.stage) that.stage.update();
});
}
if (style!==false) zimStyleTransforms(this, DS);
this.clone = function() {
var kb = new zim.Keyboard(labels, backgroundColor, color, shiftBackgroundColor, shiftHoldBackgroundColor, placeBackgroundColor, cursorColor, shadeAlpha, margin, corner, draggable, placeClose, shadowColor, shadowBlur, container, data, place, special, rtl, hardKeyboard, style, this.group, inherit);
return that.cloneProps(kb);
}
this.dispose = function(a,b,disposing) {
background.removeAllEventListeners();
if (that.keydownEvent) window.removeEventListener("keydown", that.keydownEvent);
that.zimContainer_dispose();
return true;
}
}
zim.extend(zim.Keyboard, zim.Container, "clone, dispose", "zimContainer", false);
//-67.2
/*--
zim.Organizer = function(width, list, useAdd, useRemove, usePosition, autoAdd, autoRemove, autoPosition, addForward, removeForward, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, color, rollColor, selectedColor, selectedRollColor, spacing, corner, keyEnabled, gradient, gloss, backdropColor, style, group, inherit)
Organizer
zim class - extends a zim.Tabs which extends a zim.Container which extends a createjs.Container
DESCRIPTION
A Tabs bar of interface for organizing a ZIM List.
This includes add, up, down, toTop, toBottom and remove icon buttons.
The Organizer can sit above the list and allow the user to add, remove and reorder the list.
Adding an item will add an empty button - this would need to be filled with the user input, etc.
If the user input is not ready, the autoAdd parameter can be set to false.
The change event will report an orgType of "add" and the add() method can be used when the input is ready.
The same for positioning or removing if desired.
See: https://zimjs.com/explore/organizer.html
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var organizer = new Organizer(250)
.change(function () {
if (organizer.orgType=="add") organizer.orgItem.text = "new";
});
new List({
width:250
organizer:organizer // pass the organizer to the list
});
.center()
.mov(0,40);
stage.update();
// OR
var list = new List(250)
.center()
.mov(0,40);
var organizer = new Organizer(250, list)
.center()
.mov(0,-80)
.change(function () {
if (organizer.orgType=="add") organizer.orgItem.text = "new";
});
stage.update();
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - (default 300) width of Tabs - this will determine the height as the Buttons are square.
There is no vertical version of an Organizer.
list - (default null) an ZIM List object to control - or null to add later with the list property
useAdd - default(true) set to false to not include the add button
useRemove - default(true) set to false to not include the remove button
usePosition - default(true) set to false to not include the position buttons (up, down, toTop, toBottom)
autoAdd - default(useAdd) set to false to not automatically add an item
the "change" event will still be dispatched and the orgType will be "add"
the add() method can be used to add user input for instance
autoRemove - default(useRemove) set to false to not automatically add an item
the "change" event will still be dispatched and the orgType will be "remove"
the remove() method can be used to manually remove
autoPosition - default(usePosition) set to false to not automatically position an item
the "change" event will still be dispatched and the orgType will be "up", "down", "top", "bottom"
the up(), down(), toTop(), toBottom() methods can be used to manually position
addForward - (default true) set to false to add item behind the current item (in list index) when adding
removeForward - (default true) set to false to select the item before the current item (in list index) when deleting
backgroundColor - (default "#777") the background color of the buttons
rollBackgroundColor - (default "#555") the background color of the button as rolled over
selectedBackgroundColor - (default "#444") the background color of the button when selected
color - (default "white") the text color of a deselected button when not rolled over
rollColor - (default color) the rollover color
selectedColor - (default color) the text color of the selected button
selectedRollColor - (default color) the text color of the rolled over selected button
spacing - (default 2) the distance between the buttons
corner - (default 0) the corner radius of the tabs
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
keyEnabled - (default true) so tab key cycles through tabs, shift tab backwards
gradient - (default null) 0 to 1 (try .3) adds a gradient to the buttons
gloss - (default null) 0 to 1 (try .1) adds a gloss to the buttons
backdropColor - (default "#333") the background color of the list window (any CSS color)
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
add(index, item, clone) - manually add item at index - both are optional - index defaults to current index
clone defaults to false - set to true to add a clone of the item
up(index) - move item up one index number in list - index defaults to current index
down(index) - move item down one index number in list - index defaults to current index
toTop(index) - move item to top of list (index 0) - index defaults to current index
toBottom(index) - move item bottom of list (index length-1) - index defaults to current index
remove(index) - manually remove item at index - index defaults to current index
setButtons() - manually rotate buttons to match List direction - automatically done when added to list or list is initially added to organizer
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: All Tab methods
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
list - the list the organizer is operating on
lastIndex - read-only selected index before change event is dispatched
orgIndex - read-only current index of list - same as list.currentIndex
orgItem - read-only selected item of list - same as list.selected
orgType - read-only type of button pressed - "add", "remove", "up", "down", "top", "bottom"
removedItem - a reference to the item that has been removed when removed button is pressed or remove() is called
group - used when the object is made to add STYLE with the group selector (like a CSS class)
ALSO: All Tab properties
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
dispatches a "change" event when the buttons are pressed (may be the same button again)
use orgType for what type "add", "remove", "up", "down", "top", "bottom"
use orgIndex or list.currentIndex for current list index
use orgItem or list.selected for selected item
use removedItem for a removed item
use lastIndex for index before change
ALSO: All Tab events
ALSO: See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+67.3
zim.Organizer = function(width, list, useAdd, useRemove, usePosition, autoAdd, autoRemove, autoPosition, addForward, removeForward, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, color, rollColor, selectedColor, selectedRollColor, spacing, corner, keyEnabled, gradient, gloss, backdropColor, style, group, inherit) {
var sig = "width, list, useAdd, useRemove, usePosition, autoAdd, autoRemove, autoPosition, addForward, removeForward, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, color, rollColor, selectedColor, selectedRollColor, spacing, corner, keyEnabled, gradient, gloss, backdropColor, style, group, inherit";
var duo; if (duo = zob(zim.Organizer, arguments, sig, this)) return duo;
z_d("67.3");
this.group = group;
var DS = style===false?{}:zim.getStyle("Organizer", this.group, inherit);
if (zot(width)) width = DS.width!=null?DS.width:(list&&list.vertical)?list.width:300;
if (zot(useAdd)) useAdd = DS.useAdd!=null?DS.useAdd:true;
if (zot(useRemove)) useRemove = DS.useRemove!=null?DS.useRemove:true;
if (zot(usePosition)) usePosition = DS.usePosition!=null?DS.usePosition:true;
if (zot(autoAdd)) autoAdd = DS.autoAdd!=null?DS.autoAdd:useAdd;
if (zot(autoRemove)) autoRemove = DS.autoRemove!=null?DS.autoRemove:useRemove;
if (zot(autoPosition)) autoPosition = DS.autoPosition!=null?DS.autoPosition:usePosition;
if (zot(addForward)) addForward = DS.addForward!=null?DS.addForward:true;
if (zot(removeForward)) removeForward = DS.removeForward!=null?DS.removeForward:true;
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"#777";
if (zot(rollBackgroundColor)) rollBackgroundColor = DS.rollBackgroundColor!=null?DS.rollBackgroundColor:"#555";
if (zot(selectedBackgroundColor)) selectedBackgroundColor = DS.selectedBackgroundColor!=null?DS.selectedBackgroundColor:"#333";
if (zot(color)) color = DS.color!=null?DS.color:"white";
if (zot(rollColor)) rollColor = DS.rollColor!=null?DS.rollColor:color;
if (zot(selectedColor)) selectedColor = DS.selectedColor!=null?DS.selectedColor:color;
if (zot(selectedRollColor)) selectedRollColor = DS.selectedRollColor!=null?DS.selectedRollColor:color;
if (zot(spacing)) spacing = DS.spacing!=null?DS.spacing:1;
if (zot(corner)) corner = DS.corner!=null?DS.corner:0;
if (zot(gradient)) gradient = DS.gradient!=null?DS.gradient:.2;
if (zot(gloss)) gloss = DS.gloss!=null?DS.gloss:null;
if (zot(backdropColor)) backdropColor = DS.backdropColor!=null?DS.backdropColor:null;
if (!Array.isArray(corner)) {
corner = [corner, corner, corner, corner];
}
if (!useAdd && !usePosition && !useRemove) return; // will lead to errors...
var buttonNum = (useAdd?1:0) + (usePosition?4:0) + (useRemove?1:0);
var buttonSize = (width+spacing) / buttonNum;
var buttonStyle = {
width:buttonSize,
height:buttonSize,
label:"",
shadowColor:-1,
gradient:gradient,
corner:corner,
backgroundColor:backgroundColor,
rollBackgroundColor:rollBackgroundColor
}
var buttons = this.buttons = [];
var addIcon = new zim.Shape();
addIcon.graphics.f(color).p("AAAA4Ih6B8Ig5g4IB8h8Ih7h6IA4g5IB6B8IB7h8IA5A5Ih8B6IB8B7Ig5A5g");
if (useAdd) buttons.push(new zim.Button({icon:addIcon.sca(.55).rot(-45).reg(1), inherit:buttonStyle}));
if (usePosition) {
var arrowIcon = new zim.Shape();
arrowIcon.graphics.f(color).p("AiJieIETCeIkTCfg");
buttons.push(new zim.Button({icon:arrowIcon.sca(.6).rot(list&&!list.vertical?180:-90).reg(-2), inherit:buttonStyle}));
buttons.push(new zim.Button({icon:arrowIcon.clone().sca(.6).rot(list&&!list.vertical?0:90).reg(-2), inherit:buttonStyle}));
var endIcon = new zim.Shape();
endIcon.graphics.f(color).p("AiFCLIAAkVIBXAAIAAEVgAgiAAICoiHIAAEQg");
buttons.push(new zim.Button({icon:endIcon.sca(.62).rot(list&&!list.vertical?0:90).reg(0), inherit:buttonStyle}));
buttons.push(new zim.Button({icon:endIcon.clone().sca(.62).rot(list&&!list.vertical?180:-90).reg(0), inherit:buttonStyle}));
}
if (useRemove) buttons.push(new zim.Button({icon:addIcon.clone().rot(0).sca(.55), inherit:buttonStyle}));
if (buttons.length==0) buttons = [""]
this.zimTabs_constructor(width, buttonSize, buttons, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, color, rollColor, selectedColor, selectedRollColor, false, spacing, true, false, corner, null, true, gradient, gloss, null, null, null, null, null, null, null, null, null, null, backdropColor);
var that = this;
that.list = list;
that.type = "Organizer";
that.setButtons = function() {
if (usePosition) {
var startIndex = useAdd?1:0;
if (buttons[startIndex+0]) buttons[startIndex+0].icon.rotation = that.list&&!that.list.vertical?180:-90;
if (buttons[startIndex+1]) buttons[startIndex+1].icon.rotation = that.list&&!that.list.vertical?0:90;
if (buttons[startIndex+2]) buttons[startIndex+2].icon.rotation = that.list&&!that.list.vertical?0:90;
if (buttons[startIndex+3]) buttons[startIndex+3].icon.rotation = that.list&&!that.list.vertical?180:-90;
}
}
var listEvent = false;
var lastList = list;
that.change(function (e) {
// handle dynamically adding event to list, delayed list or changed list
if ((!listEvent && that.list) || (that.list && that.list != lastList)) {
if (that.list != lastList) {if (lastList) lastList.noChange();}
that.list.change(function (e) {
that.orgItem = that.list.selected;
that.orgIndex = that.list.selectedIndex;
});
listEvent = true;
lastList = that.list;
}
var val = e.target.selectedIndex;
if (!useAdd) val++;
if (!usePosition && (!useAdd || val>0)) val = 5;
var badIndex = zot(that.list.selectedIndex) || that.list.selectedIndex<0;
if (badIndex) that.currentValue = null;
that.lastIndex = that.list.selectedIndex;
switch(val) {
case 0: // add
if (autoAdd) {
var index = Math.max(0,that.list.selectedIndex);
that.add(index);
}
that.orgType = "add";
break;
case 1: // up
if (badIndex) break;
if (autoPosition) {
var index = that.list.selectedIndex;
that.up(index);
}
that.orgType = "up";
break;
case 2: // down
if (badIndex) break;
if (autoPosition) {
var index = that.list.selectedIndex;
that.down(index);
}
that.orgType = "down";
break;
case 3: // top
if (badIndex) break;
if (autoPosition) {
var index = that.list.selectedIndex;
that.toTop(index);
}
that.orgType = "top";
break;
case 4: // bottom
if (badIndex) break;
if (autoPosition) {
var index = that.list.selectedIndex;
that.toBottom(index);
}
that.orgType = "bottom";
break;
case 5: // remove
if (badIndex) break;
if (autoRemove) {
var index = that.list.selectedIndex;
that.remove(index);
}
that.orgType = "remove";
break;
}
});
this.add = function(index, item, clone) {
if (zot(index)) index = that.lastIndex;
if (zot(item)) item = "";
if (addForward) {
var index = Math.min(that.list.length, Math.max(0,that.list.selectedIndex)+1);
} else {
var index = Math.max(0,that.list.selectedIndex);
}
that.list.addAt(item, index, clone);
that.list.selectedIndexPlusPosition = index;
that.orgItem = that.list.selected;
that.orgIndex = that.list.selectedIndex;
}
this.up = function(index) {
if (zot(index)) index = that.lastIndex;
var button = that.list.items[index];
if (zot(button)) return;
that.list.removeAt(1, index);
that.list.addAt(button, index-1);
that.list.selectedIndexPlusPosition = Math.max(0,index-1);
that.orgItem = that.list.selected;
that.orgIndex = that.list.selectedIndex;
}
this.down = function(index) {
if (zot(index)) index = that.lastIndex;
var button = that.list.items[index];
if (zot(button)) return;
that.list.removeAt(1, index);
that.list.addAt(button, index+1);
that.list.selectedIndexPlusPosition = Math.min(that.list.length-1,index+1);
that.orgItem = that.list.selected;
that.orgIndex = that.list.selectedIndex;
}
this.toTop = function(index) {
if (zot(index)) index = that.lastIndex;
var button = that.list.items[index];
if (zot(button)) return;
that.list.removeAt(1, index);
that.list.addAt(button, 0);
that.list.first();
that.orgItem = that.list.selected;
that.orgIndex = that.list.selectedIndex;
}
this.toBottom = function(index) {
if (zot(index)) index = that.lastIndex;
var button = that.list.items[index];
if (zot(button)) return;
that.list.removeAt(1, index);
that.list.addAt(button, that.list.length);
that.list.last();
that.orgItem = that.list.selected;
that.orgIndex = that.list.selectedIndex;
}
this.remove = function(index) {
if (zot(index)) index = that.lastIndex;
that.removedItem = that.list.selected;
var index = Math.max(0,that.list.selectedIndex);
that.list.removeAt(1, index);
if (removeForward) {
var index = Math.max(0,that.list.selectedIndex);
} else {
var index = Math.max(0,that.list.selectedIndex-1);
}
that.list.selectedIndexPlusPosition = Math.min(that.list.length-1, index);
that.orgItem = that.list.selected;
that.orgIndex = that.list.selectedIndex;
}
if (style!==false) zimStyleTransforms(this, DS);
this.clone = function() {
return that.cloneProps(new zim.Organizer(width, list, useAdd, useRemove, usePosition, autoAdd, autoRemove, autoPosition, addForward, removeForward, backgroundColor, rollBackgroundColor, selectedBackgroundColor, selectedRollBackgroundColor, color, rollColor, selectedColor, selectedRollColor, spacing, corner, keyEnabled, gradient, gloss, backdropColor, style, that.group, inherit));
}
}
zim.extend(zim.Organizer, zim.Tabs, "clone", "zimTabs", false);
//-67.3
/*--
zim.Marquee = function(width, height, items, time, transition, speed, direction, marginLeft, marginRight, marqueeType, borderColor, borderWidth, refresh, mix, style, group, inherit)
Marquee
zim class - extends a zim.Container which extends a createjs.Container
DESCRIPTION
A display for ads and promos using an optional ZIM Indicator with pause button.
The Marquee uses the ZIM Pages class to transition multiple items.
The items can be interactive ZIM objects made ahead of time and passed into the items parameters
Images can also be loaded with the load() method
See: https://zimjs.com/marquee.html for an example
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var promo1 = new Container(600, 200);
new Rectangle(promo1.width, promo1.height, yellow).addTo(promo1);
new Circle(30, red).center(promo1).drag();
// could be more
// optionally or alternatively, specify a Marquee object
// there can be multiple image properties using end src as key
// just use null as value if no URL
var marqueeData = {"retina.jpg": ["https://zimjs.com/retina.html", "_blank"]};
var marqueePath = "assets/";
// create Marquee
// note the actual width of marquee will be 25+25 more for added margins (optional)
var marquee = new Marquee(600, 200, [promo1])
.center()
.load(marqueeData, marqueePath);
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - (default 300) width of marquee content
final marquee width will have marginLeft and marginRight added to this width
height - (default 100) height of content and marquee
items - default(null) an array of Display Objects - can be interactive
time - default(5000) time interval in ms for changing items
also see marqueeTime property for each item to individually override the time for viewing
transition - default("slide") the transition between items
options are: "none", "reveal", "slide", "fade", "clear", "black", "white"
speed - default(500) speed of transition in ms
direction - default("right") location of next item relative to current item
options are: "right", "left", "up", "down"
marginLeft - default(25) width at left of content for Indicator and Pause button
set to 0 to not show indicator and pause button
marginRight - default(25) width at right of content for Z logo with animated MARQUEE
set to 0 to not show Z logo with animated MARQUEE
marqueeType - (default "dot" or "circle") the Indicator type - also "box" or "square"
borderColor - (default "#333") border color - any ZIM or HTML color - set to -1 for no border
borderWidth - (default 1) width of border if borderColor - set to 0 for no border
refresh - (default 30*60*1000) page refresh to handle browser memory build
mix - (default true) randomize content and then play in that order - different for each page load
note: loaded files will always come after initial marquee items
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
add(obj, url, target) - add a Display Object (obj) - can be interactive content - returns obj for chaining
can provide an overall url and target for url
but often will provide navigation button, etc. as part of interactive content
remove(obj) - remove an object from the marquee - returns obj for chaining
will also call a dispose() method on the obj if there is one
go(page) - transition to specific page (obj) or index - returns obj for chaining
pause(state, immediate) - pause or unpause the Marquee - returns obj for chaining
can be used by interactive code to pause Marquee when interacting
immediate (default false) set to true to make the Marquee go to next item right away when unpausing (no effect when pausing)
load(data, path) - Marquee object for images their optional action url and target: - returns obj for chaining
data in format: {imageSrc:"actionURL", imageSrc:["actionURL", "target"], etc.}
path: optional directory location such as a relative path: "assets/"
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
content - a reference to the ZIM Container that holds the content
pages - a reference to the ZIM Pages object that holds the items
use pages.pages to access an array of pages, etc. - see Pages Class
button - a reference to the pause/play button if there is one
indicator - a reference to the ZIM Indicator if there is one - see Indicator Class
selectedIndex - the selected index of the Marquee
selected - the selected item of the Marquee
lastSelected - the last selected item of the Marquee
time - get or set the time of the marquee (between changing items)
speed - get the speed of the transition
paused - read only property as to whether the Marquee is paused - see pause() method
interval - a reference to the ZIM interval
left - a reference to the left Container
right - a reference to the right Container if there is one
icon - a reference to the Z icon if there is one
label - a reference to the MARQUEE Label that pops out of the Z if there is one
eg. label.visible = false to not show label popping out
marqueeLoader - a reference to the ZIM loadAssets queue if load() is used
group - used when the object is made to add STYLE with the group selector (like a CSS class)
Each item gets a marquee property that points to the ZIM marquee it is in
Each item gets a marqueViews property recording how many times viewed
Each item can have a marqueeTime property set to ms to customize its view time
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
EVENTS
dispatches a "page" event when item starts to change
dispatches a "pagetransitioned" event when item finishes changing
ALSO: See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+67.4
zim.Marquee = function(width, height, items, time, transition, speed, direction, marginLeft, marginRight, marqueeType, borderColor, borderWidth, refresh, mix, style, group, inherit) {
var sig = "width, height, items, time, transition, speed, direction, marginLeft, marginRight, marqueeType, borderColor, borderWidth, refresh, mix, style, group, inherit";
var duo; if (duo = zob(zim.Marquee, arguments, sig, this)) return duo;
z_d("67.4");
this.group = group;
var DS = {};
var DS = style===false?{}:zim.getStyle("Marquee", this.group, inherit);
var that = this;
if (zot(width)) width = DS.width!=null?DS.width:300;
if (zot(height)) height = DS.height!=null?DS.height:100;
if (zot(time)) time = DS.time!=null?DS.time:2000;
if (zot(transition)) transition = DS.transition!=null?DS.transition:"slide";
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:"#333";
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:1;
if (borderColor < 0 || borderWidth < 0) borderColor = borderWidth = null;
else if (borderColor!=null && borderWidth==null) borderWidth = 1;
if (zot(marginLeft)) marginLeft = DS.marginLeft!=null?DS.marginLeft:25;
if (zot(marginRight)) marginRight = DS.marginRight!=null?DS.marginRight:25;
if (zot(speed)) speed = DS.speed!=null?DS.speed:500;
if (zot(direction)) direction = DS.direction!=null?DS.direction:"right";
if (zot(refresh)) refresh = DS.refresh!=null?DS.refresh:30*60*1000; // 30 minutes
if (zot(mix)) mix = DS.mix!=null?DS.mix:true;
this.zimContainer_constructor(width+marginLeft+marginRight,height,null,null,false);
this.type = "Marquee";
this.speed = speed;
var mask = new zim.Rectangle(width-1,height-1,clear).addTo(that).mov(marginLeft+.5, .5);
var content = this.content = new zim.Container(width, height)
.loc(marginLeft,0,that)
.setMask(mask);
var pages = this.pages = new zim.Pages(null, transition, speed, null, content).addTo(content);
var startCheck = false;
this.add = function(obj, url, target, skip) {
obj.scaleTo(content);
if (url) obj.cur().on("click", function() {
zgo(url, target);
})
pages.addPage(obj);
obj.marqueeViews = 0;
obj.marquee = that;
if (!startCheck) startSelection();
if (!skip) makeIndicator();
if (border) border.top();
}
this.remove = function(obj) {
if (that.selected == obj) {
if (that.pages.pages.length == 1) return;
var newIndex = that.selectedIndex+1;
if (newIndex == that.pages.pages.length) newIndex = 0;
that.pages.go(newIndex,null,null,0);
zim.timeout(20, function () {
that.pages.removePage(obj);
if (obj.dispose) obj.dispose();
makeIndicator();
});
} else {
that.pages.removePage(obj);
if (obj.dispose) obj.dispose();
makeIndicator();
}
}
function startSelection() {
startCheck = true;
that.selectedIndex = 0;
that.selected = pages.pages[that.selectedIndex].page;
that.lastSelected = null;
if (that.selected.marqueeOn) that.selected.marqueeOn();
that.interval = zim.interval(time, function () {
that.go();
});
}
if (!zot(items) && !Array.isArray(items)) items = [items];
if (items && items.length > 0) {
if (mix) zim.shuffle(items);
zim.loop(items, function (item) {
that.add(item, null, null, true); // don't make indicator
});
}
if (refresh > 0) zim.timeout(refresh, function(){
location.reload();
});
that.go = function(page) {
that.selected.marqueeViews+=1;
if (that.selected.marqueeOff) that.selected.marqueeOff();
if (page) {
that.selected = page;
zim.loop(pages.pages, function (p,i) {
if (p.page==page) {
that.selectedIndex = i;
return;
}
});
that.interval.interval = that.selected.marqueeTime ? that.selected.marqueeTime : time;
that.interval.pause(pause.toggled, null, true); // reset time
} else {
var next = that.selectedIndex+1;
that.selectedIndex = next%pages.pages.length;
that.selected = pages.pages[that.selectedIndex].page;
that.interval.time = that.selected.marqueeTime ? that.selected.marqueeTime : time;
}
that.dispatchEvent("page");
if (that.selected.marqueeOn) that.selected.marqueeOn();
pages.go(that.selected, direction, transition, speed);
}
pages.on("pagetransitioned", function () {
that.dispatchEvent("pagetransitioned");
if (that.indicator) that.indicator.selectedIndex = that.selectedIndex;
});
// ~~~~~~~~~~~~
// LEFT
var _paused = false;
var left = that.left = new zim.Container(marginLeft-4,height-4);
var pauseIcon = new zim.Shape().sca(.6);
pauseIcon.graphics.f(light).mt(0,0).p("AAhCLIAAkVIBXAAIAAEVgAh3CLIAAkVIBXAAIAAEVg");
var playIcon = new zim.Shape().sca(.6).reg(-2,0);
playIcon.graphics.f(light).mt(0,0).p("AiJieIETCeIkTCfg");
var pause = that.button = new zim.Button({
label:"",
icon:pauseIcon,
toggleIcon:playIcon,
width:45,
height:45,
corner:0,
shadowBlur:0
})
.scaleTo(left, 100)
.pos(0,0,false,true,left);
pause.on("click", function () {
if (that.interval) that.interval.pause(pause.toggled);
_paused = pause.toggled;
that.stage.update();
});
var prop;
function makeIndicator() {
if (zot(marginLeft) || marginLeft==0) return;
var gutterLeft = 4*marginLeft/25;
left.pos((marginLeft-left.width)-gutterLeft,gutterLeft/2,false,true,that)
if (that.indicator) {
that.indicator.dispose();
that.indicator.removeFrom();
}
if (!prop) prop = new zim.Proportion(8,16,left.width+gutterLeft,left.width/2+gutterLeft,-1);
that.indicator = new zim.Indicator({
width:(pages.pages.length<=2?pages.pages.length:pages.pages.length-1)*(left.width-3),
height: prop.convert(pages.pages.length),
num: pages.pages.length,
shadowBlur:-1,
interactive:true,
scale:1.2,
indicatorType:marqueeType
});
that.indicator.fit(0,0,height-pause.height,pause.width);
that.indicator.rot(direction=="down"?-90:90)
.center(left)
.pos(null,left.width-gutterLeft/2,null,true);
that.indicator.selectedIndex = that.selectedIndex;
that.indicator.on("change", function () {
that.go(pages.pages[that.indicator.selectedIndex].page)
});
}
makeIndicator();
// ~~~~~~~~~~~~~
// RIGHT
if (!zot(marginRight) && marginRight>0 && typeof zimDefaultFrame != "undefined" && zimDefaultFrame) {
var gutterRight = 4*marginRight/25;
var right = that.right = new zim.Container(45,270)
var icon = that.icon = zimDefaultFrame.makeIcon(zim.grey, zim.lighter, zim.silver)
.sca(.5)
.pos(0,0,true,true,right)
.mov(0,0)
.cur()
// .sha(white,0,1,1);
icon.on("mouseover", function () {
lab.animate({props:{scaleX:1}, time:500, ease:"backOut", override:true});
icon.stage.update();
});
icon.on("mouseout", function () {
lab.animate({props:{scaleX:0}, time:300, ease:"backIn", override:true});
icon.stage.update();
});
icon.on("mousedown", function () {
zgo("https://zimjs.com/marquee", "_blank");
})
var lab = that.label = new zim.Label({
text:"MARQUEE",
color:dark,
backgroundColor:lighter,
shiftVertical:1,
paddingVertical:5
})
.rot(-90)
.pos(0,13,true,false,right)
.reg(-10)
.sca(0,1)
.mov(0);
right.fit(0,0,marginRight-gutterRight,height-gutterRight)
right.pos(marginRight-right.width-gutterRight,gutterRight/2,true,true,that);
}
if (that.stage) that.stage.update();
this.pause = function(state, immediate) {
if (zot(state)) state = true;
if (state == _paused) return;
_paused = state;
that.interval.pause(state, immediate);
that.button.toggle(state);
}
Object.defineProperty(this, 'paused', {
get: function() {
return _paused;
},
set: function(value) {
if (zon) zogy("Marquee() - paused is read only - use pause()");
}
});
Object.defineProperty(this, 'time', {
get: function() {
return time;
},
set: function(value) {
time = value;
that.interval.time = time;
}
});
this.load = function(data, path) {
// Load any marqueeAssets with lazy loading
var a = []; // make an array of only the asset urls
if (mix) zim.shuffle(data);
zim.loop(data, function(asset) {
if (Array.isArray(asset)) a.push(asset[0]); // could have target window
else a.push(asset);
});
that.marqueeLoader = frame.loadAssets(a, path);
that.marqueeLoader.on("assetload", function (e) {
var d = data[e.asset.id];
if (Array.isArray(d)) {
var u = d[0];
var t = d[1];
} else {
var u = d;
var t = "_self";
}
that.add(e.asset, u, t);
makeIndicator();
});
return that;
}
if (!zot(borderColor)) {
var border = new zim.Rectangle(width-1, height-1, zim.clear, borderColor, borderWidth).loc(mask,null,that);
border.mouseEnabled = false;
}
if (style!==false) zimStyleTransforms(this, DS);
this.clone = function() {return that.cloneProps(new zim.Marquee(width, height, items, time, transition, speed, direction, marqueeType, borderColor, borderWidth, refresh, mix, style, this.group, inherit));}
this.dispose = function (a,b,disposing) {
if (that.interval) that.interval.clear();
if (!disposing) this.zimContainer_dispose(true);;
return true;
}
}
zim.extend(zim.Marquee, zim.Container, ["clone", "dispose"], "zimContainer");
//-67.4
/*--
zim.Loader = function(width, height, label, backgroundColor, rollBackgroundColor, color, rollColor, borderColor, borderWidth, corner, shadowColor, shadowBlur, hitPadding, gradient, gloss, dashed, backing, rollBacking, rollPersist, icon, rollIcon, toggle, toggleBacking, rollToggleBacking, toggleIcon, rollToggleIcon, toggleEvent, frame, style, group, inherit)
Loader
zim class - extends a zim.Button which extends a zim.Container
DESCRIPTION
Loader lets you upload images and access them as a Bitmap (available in the loaded event function)
Loader uses the HTML input type=file tag and overlays this with a createjs DOMElement.
Loader is a Button so can be displayed for the user to click on.
It defaults to a dashed line region as you can also drag and drop files to the loader.
You can also save an image using the save() method to a new browser window for the user to save
NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
EXAMPLE
var loader = new Loader({
frame:frame,
label:"UPLOAD PIC OR DROP PICS HERE",
width:700,
height:400,
corner:50
}).center(stage);
loader.on("loaded", function(e) {
loop(e.bitmaps, function(bitmap){
bitmap.centerReg(stage).drag();
});
loader.removeFrom(stage);
stage.update();
});
// and to later save for instance in a button event:
saveButton.on("click") {
loader.save(stage); // or some other container... can specify crop bounds too
}
END EXAMPLE
PARAMETERS
** supports DUO - parameters or single object with properties below
** supports OCT - parameter defaults can be set with STYLE control (like CSS)
width - (default 250) the width of the button
height - (default 70) the height of the button
label - (default "UPLOAD PIC") ZIM Label or plain text
backgroundColor - (default "rgba(0,0,0,.05)") background color of button (any CSS color)
rollBackgroundColor - (default "rgba(0,0,0,.1)") rollover color of button backbground
color - (default "rgba(0,0,0,.5)") text color of button (any CSS color)
rollColor - (default color) rollover text color of button
borderColor - (default rgba(0,0,0,.3)) the color of the border
borderWidth - (default 1) thickness of the border
corner - (default 0) the round of the corner (set to 0 for no corner)
can also be an array of [topLeft, topRight, bottomRight, bottomLeft]
shadowColor - (default "rgba(0,0,0,.3)") set to -1 for no shadow
shadowBlur - (default 14) how blurred the shadow is if the shadow is set
hitPadding - (default 0) adds extra hit area to the button (good for mobile)
gradient - (default 0) 0 to 1 (try .3) adds a gradient to the button
gloss - (default 0) 0 to 1 (try .1) adds a gloss to the button
backing - (default null) a Display object for the backing of the button (eg. Shape, Bitmap, Container, Sprite)
see ZIM Pizzazz module for a fun set of Button Shapes like Boomerangs, Ovals, Lightning Bolts, etc.
https://zimjs.com/bits/view/pizzazz.html
rollBacking - (default null) a Display object for the backing of the rolled-on button
rollPersist - (default false) set to true to keep rollover state when button is pressed even if rolling off
icon - (default false) set to display object to add icon at the center of the button and remove label
https://zimjs.com/bits/view/icons.html
rollIcon - (default false) set to display object to show icon on rollover
toggle - (default null) set to string to toggle with label or display object to toggle with icon or if no icon, the backing
rollToggle - (default null) set to display object to toggle with rollIcon or rollBacking if no icon
there is no rollToggle for a label - that is handled by rollColor on the label
toggleEvent - (default mousedown for mobile and click for not mobile) what event causes the toggle
dashed - (default true) set to false to turn off the dashed for the border
frame - (default the zimDefaultFrame) a reference to the Frame (to scale and position the HTML tag)
style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
inherit - (default null) used internally but can receive an {} of styles directly
METHODS
resize() - call the resize event if the scale or position of the Loader is changed
this will sync the location of the HTML input tag
resize() is only needed if the scale or x, y of the Loader (or its container) is changed
it is not needed for general window resizing - the Loader handles this
Note: if the Frame itself changes location in the HTML document, call a frame.update()
this will then dispatch an update event to the Loader and it will resize()
this is not needed if resizing the window or scrolling - see Frame update() method docs
save(content, filename, x, y, width, height, cached, cachedBounds, type, data) - save a picture (supports ZIM DUO)
content - the Display object to be saved such as a Container, Bitmap, etc.
filename - (default random) - the text name of the file (with or without extension - also see type)
x, y, width, height - the cropping bounds on that object otherwise defaults to 0,0,stageW,stageH
cached - (default false) set to true if the object is currently already cached
cachedBounds - if you are saving a different bounds than was previously cached
setting the bounds here (createjs.Rectangle) will restore the cache to the previous bounds
type - (default "png") set to "jpeg" for jpeg
data - (default false) set to true to save as base64 data - thanks Andi Ermi for the request
otherwise save returns the object for chaining
Button methods:
setBacking(type, newBacking) - dynamically set any type of backing for button (if null removes backing for that type)
Backing types are: "backing", "rollBacking", "toggleBacking", "rollToggleBacking", "waitBacking", "rollWaitBacking"
note - all backing will have a pattern property if a pattern is set as a backing
setIcon(type, newIcon) - dynamically set any type of icon for button (if null removes icon for that type)
Icon types are: "icon", "rollIcon", "toggleIcon", "rollToggleIcon", "waitIcon", "rollWaitIcon"
toggle(state) - forces a toggle of label if toggle param is string, else toggles icon if icon is set or otherwise toggles backing
state defaults to null so just toggles
pass in true to go to the toggled state and false to go to the original state
hasProp(property as String) - returns true if property exists on object else returns false
clone() - makes a copy with properties such as x, y, etc. also copied
dispose() - removes from parent, removes event listeners - must still set outside references to null for garbage collection
ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as:
drag(), hitTestRect(), animate(), sca(), reg(), mov(), center(), centerReg(),
addTo(), removeFrom(), loop(), outline(), place(), pos(), alp(), rot(), setMask(), etc.
ALSO: See the CreateJS Easel Docs for Container methods, such as:
on(), off(), getBounds(), setBounds(), cache(), uncache(), updateCache(), dispatchEvent(),
addChild(), removeChild(), addChildAt(), getChildAt(), contains(), removeAllChildren(), etc.
PROPERTIES
type - holds the class name as a String
tag - the HTML input tag of type file - used for uploading
frame - get or set the frame - set this if changing frames
group - used when the object is made to add STYLE with the group selector (like a CSS class)
Button properties:
** setting widths and heights adjusts scale not bounds and getting these uses the bounds dimension times the scale
width - gets or sets the width. Setting the width will scale the height to keep proportion (see widthOnly below)
height - gets or sets the height. Setting the height will scale the width to keep proportion (see heightOnly below)
widthOnly - gets or sets the width. This sets only the width and may change the aspect ratio of the object
heightOnly - gets or sets the height. This sets only the height and may change the aspect ratio of the object
level - gets or sets the level of the object in its parent container (or the stage) - a property for parent.getChildIndex() and parent.setChildIndex()
text - references the text property of the Label object of the button
label - gives access to the label
backgroundColor - get or set non-rolled on backing color (if no backing specified)
rollBackgroundColor - get or set rolled on backing color
color - get or set non-rolled on text color (if no icon specified)
rollColor - get or set rolled on text color
backing - references the backing of the button
rollBacking - references the rollBacking (if set)
icon - references the icon of the button (if set)
rollIcon - references the rollIcon (if set)
toggleObj - references the toggle object (string or display object if set)
rollToggle - references the rollToggle (if set)
toggled - true if button is in toggled state, false if button is in original state
enabled - default is true - set to false to disable
rollPersist - default is false - set to true to keep rollover state when button is pressed even if rolling off
focus - get or set the focus property of the Button used for tabOrder
blendMode - how the object blends with what is underneath - such as "difference", "multiply", etc. same as CreateJS compositeOperation
ALSO: See the CreateJS Easel Docs for Container properties, such as:
x, y, rotation, scaleX, scaleY, regX, regY, skewX, skewY,
alpha, cursor, shadow, mouseChildren, mouseEnabled, parent, numChildren, etc.
ACTIONEVENT
This component is affected by the general ACTIONEVENT setting
The default is "mousedown" - if set to something else the component will act on click (press)
EVENTS
loaded - is dispatched when the image(s) are uploaded - the event object comes with the following properties:
e.bitmaps - an array of Bitmap objects of the loaded images
e.bitmap - the first Bitmap to be created from the loaded images
e.lastBitmap - the last Bitmap to be created from the loaded images
e.total - the total Bitmap objects to be created from the loaded images
ALSO: See the CreateJS Easel Docs for Container events, such as:
added, click, dblclick, mousedown, mouseout, mouseover, pressmove, pressup, removed, rollout, rollover
--*///+67.5
zim.Loader = function(width, height, label, backgroundColor, rollBackgroundColor, color, rollColor, borderColor, borderRollColor, borderWidth, corner, shadowColor, shadowBlur, hitPadding, gradient, gloss, dashed, backing, rollBacking, rollPersist, icon, rollIcon, toggle, toggleBacking, rollToggleBacking, toggleIcon, rollToggleIcon, toggleEvent, frame, style, group, inherit) {
var sig = "width, height, label, backgroundColor, rollBackgroundColor, color, rollColor, borderColor, borderRollColor, borderWidth, corner, shadowColor, shadowBlur, hitPadding, gradient, gloss, dashed, backing, rollBacking, rollPersist, icon, rollIcon, toggle, toggleBacking, rollToggleBacking, toggleIcon, rollToggleIcon, toggleEvent, frame, style, group, inherit";
var duo; if (duo = zob(zim.Loader, arguments, sig, this)) return duo;
z_d("67.5");
this.group = group;
var DS = style===false?{}:zim.getStyle("Loader", this.group, inherit);
if (zot(width)) width = DS.width!=null?DS.width:250;
if (zot(height)) height = DS.height!=null?DS.height:70;
if (zot(backgroundColor)) backgroundColor = DS.backgroundColor!=null?DS.backgroundColor:"rgba(0,0,0,.05)";
if (zot(rollBackgroundColor)) rollBackgroundColor = DS.rollBackgroundColor!=null?DS.rollBackgroundColor:"rgba(0,0,0,.1)";
if (zot(color)) color = DS.color!=null?DS.color:"rgba(0,0,0,.5)";
if (zot(rollColor)) rollColor = DS.rollColor!=null?DS.rollColor:color;
if (zot(borderColor)) borderColor = DS.borderColor!=null?DS.borderColor:"rgba(0,0,0,.3)";
if (zot(borderWidth)) borderWidth = DS.borderWidth!=null?DS.borderWidth:1;
if (zot(dashed)) dashed = DS.dashed!=null?DS.dashed:true;
if (zot(corner)) corner = DS.corner!=null?DS.corner:0;
if (zot(label)) label = DS.label!=null?DS.label:new zim.Label({
text:"UPLOAD PIC", color:color, rollColor:rollColor, valign:"center", align:"center",
backing:"ignore", shadowColor:"ignore", shadowBlur:"ignore", backgroundColor:"ignore",
group:this.group
});
if (zot(frame)) {
if (zimDefaultFrame) {
frame = zimDefaultFrame;
} else {
if (zon) {zog("zim.Loader - please provide a reference to zim Frame");} return;
}
}
// this.zimButton_constructor();
this.zimButton_constructor(width, height, label, backgroundColor, rollBackgroundColor, color, rollColor, borderColor, borderRollColor, borderWidth, corner, shadowColor, shadowBlur, hitPadding, gradient, gloss, dashed, backing, rollBacking, rollPersist, icon, rollIcon, toggle, toggleBacking, rollToggleBacking, toggleIcon, rollToggleIcon, toggleEvent, null, null, null, null, null, null, null, null, null, null, null, null, false);
this.type = "Loader";
var that = this;
var stage = frame.stage;
label = that.label;
var uploadTag = that.tag = document.createElement("input");
document.body.appendChild(uploadTag);
uploadTag.setAttribute("type", "file");
uploadTag.setAttribute("multiple", "multiple");
uploadTag.setAttribute("aria-hidden", true);
uploadTag.hidden = true;
uploadTag.style.cssText = "border:thin solid grey; z-index:2; width:"+width+"px; height:" + height + "px; overflow:hidden; outline:none;"
+ "position:absolute; left:0px; top:0px; display:none; cursor:pointer; opacity: 0; filter: alpha(opacity=0);"
this.addEventListener('mousedown', function() { // added for zim.Accessibility
uploadTag.click();
});
uploadTag.addEventListener('change', handleImage);
var upload = new createjs.DOMElement(uploadTag);
stage.addChild(upload);
upload.alpha = 0;
var pRatio = frame.retina?(window.devicePixelRatio || 1):1;
this.resize = function() {
if (!that.stage) {
uploadTag.setAttribute("aria-hidden", true);
uploadTag.hidden = true;
uploadTag.style.display = "none";
// uploadTag.previosSibling.hidden = true;
// uploadTag.previosSibling.style.display = "none";
return;
}
uploadTag.setAttribute("aria-hidden", false);
uploadTag.hidden = false;
uploadTag.style.display = "block";
// uploadTag.previosSibling.hidden = false;
// uploadTag.previosSibling.style.display = "block";
setTimeout(function() {
var point = that.localToGlobal(0, 0);
if (frame.retina) {
upload.x = frame.x/stage.scaleX + point.x/pRatio;
upload.y = frame.y/stage.scaleY + point.y/pRatio;
// CreateJS DOMElement is scaling tag as stage scales
zim.sca(upload, that.scaleX/pRatio, that.scaleY/pRatio);
} else {
upload.x = frame.x + point.x * frame.scale;
upload.y = frame.y + point.y * frame.scale;
zim.sca(upload, frame.scale*that.scaleX, frame.scale*that.scaleY);
}
stage.update();
}, 50);
return that;
}
this.resize();
that.on("added", function() {
uploadTag.style.display = "block";
uploadTag.hidden = false;
uploadTag.style.display = "block";
that.resize();
});
that.added(addedCallback);
function addedCallback() {
that.resize();
setTimeout(function() {
uploadTag.style.display = "block";
uploadTag.hidden = false;
uploadTag.style.display = "block";
}, 50);
that.on("added", addedCallback, null, true); // once
}
that.on("removed", function() {
uploadTag.style.display = "none";
uploadTag.hidden = true;
uploadTag.style.display = "none";
});
function handleImage(e) {
var files;
if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length > 0) {
files = e.dataTransfer.files;
} else {
files = e.target.files;
}
var bitmaps = [];
var firstBitmap;
var lastBitmap;
for (var i=0; isaved