zimjs 17.3.3 → 17.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/zim.js CHANGED
@@ -8258,10 +8258,34 @@ BitmapDataChannel.GREEN
8258
8258
  BitmapDataChannel.BLUE
8259
8259
 
8260
8260
  SEE:
8261
+ https://zimjs.com/zapp/Z_ADQEH - simple version
8261
8262
  https://zimjs.com/zapp/Z_X4PYD - coloring a Pic
8262
8263
  https://zimjs.com/zapp/Z_XMT78 - coloring a Tile
8263
8264
  https://github.com/u-kudox/BitmapData_for_EaselJS/tree/master/examples
8264
8265
 
8266
+ EXAMPLE
8267
+ // this is a shortened version of the examples below using internal code
8268
+ // the addBitmapData() will create take the current Bitmap and pass it to a BitmapData object
8269
+ // then take that BitmapData object and create a new Bitmap from the BitmapData
8270
+ // this is then returned by the addBitmapData()
8271
+ // the color() then applies a floodFill() internally saving a half dozen lines of code
8272
+ const assets = "ai_coloring_groovy.png";
8273
+ const path = "https://zimjs.org/assets/";
8274
+ new Frame(FIT, 1481, 745, light, dark, ready, assets, path);
8275
+ function ready() {
8276
+ const pic = new Pic("ai_coloring_groovy.png");
8277
+ const bitmap = new Bitmap(pic)
8278
+ .addBitmapData()
8279
+ .scaleTo()
8280
+ .cur()
8281
+ .center();
8282
+ const color = series(red, orange, blue, green, yellow);
8283
+ bitmap.on("mousedown", ()=>{
8284
+ bitmap.color(color); // or get from ColorPicker()
8285
+ S.update();
8286
+ });
8287
+ }
8288
+ END EXAMPLE
8265
8289
 
8266
8290
  EXAMPLE
8267
8291
  // coloring a pic with floodFill()
@@ -10640,6 +10664,26 @@ function ready() {
10640
10664
  }
10641
10665
  END EXAMPLE
10642
10666
 
10667
+ EXAMPLE
10668
+ // https://zimjs.com/zapp/Z_ADQEH - coloring a Bitmap pic
10669
+ const assets = "ai_coloring_groovy.png";
10670
+ const path = "https://zimjs.org/assets/";
10671
+ new Frame(FIT, 1481, 745, light, dark, ready, assets, path);
10672
+ function ready() {
10673
+ const pic = new Pic("ai_coloring_groovy.png");
10674
+ const bitmap = new Bitmap(pic)
10675
+ .addBitmapData()
10676
+ .scaleTo()
10677
+ .cur()
10678
+ .center();
10679
+ const color = series(red, orange, blue, green, yellow);
10680
+ bitmap.on("mousedown", ()=>{
10681
+ bitmap.color(color); // or get from ColorPicker()
10682
+ S.update();
10683
+ });
10684
+ }
10685
+ END EXAMPLE
10686
+
10643
10687
  EXAMPLE
10644
10688
  // turn a container of circles into a Bitmap
10645
10689
  const circles = new Container(W, H).addTo();
@@ -10746,6 +10790,12 @@ group - (default null) set to String (or comma delimited String) so STYLE can se
10746
10790
  inherit - (default null) used internally but can receive an {} of styles directly
10747
10791
 
10748
10792
  METHODS
10793
+ addBitmapData() - returns a new Bitmap of the original but with the CreateJS BitmapData class added as a bitmapData property
10794
+ see https://zimjs.com/docs.html?item=BitmapData
10795
+ color(color, thresholdColor, x, y) - color a Bitmap. The Bitmap must be made with addBitmapData() - or have equivilant adjustments applied.
10796
+ color - |ZIM VEE| (default red) is the color to do a BitmapData floodFill() - it will automatically be converted to the right color format
10797
+ thresholdColor (default dark) is the color for which darker colors will not be colored allowing dark lines to separate coloring areas
10798
+ x and y (default F.mouseX and F.mouseY relative to the Bitmap) an x and y inside the Bitmap coordinates to apply BitmapData floodFill()
10749
10799
  keyOut(color, tolerance, replacement) - remove color from Bitmap and a tolerance between 0-1
10750
10800
  the default color is "#389b26" which is a medium dark green
10751
10801
  the default tolerance is .1 - the higher the tolerance the less sensitive the keying process - so more colors will be removed similar to the provided color
@@ -10815,6 +10865,8 @@ imageData - data for the pixels stored in a data property of an ImageData object
10815
10865
  eg. 0,0,0,255,255,255,255,255 is a black pixel with 1 alpha and a white pixel with 1 alpha
10816
10866
  You set this before calling the Bitmap drawImageData() method
10817
10867
  See also https://developer.mozilla.org/en-US/docs/Web/API/ImageData - but let ZIM do the work
10868
+ bitmapData - if a Bitmap is created with addBitmapData() then a bitmapData property is added to reference its CreateJS BitmpaData object
10869
+ see https://zimjs.com/docs.html?item=BitmapData
10818
10870
  group - used when the object is made to add STYLE with the group selector (like a CSS class)
10819
10871
  ** bounds must be set first (or width and height parameters set) for these to work
10820
10872
  ** setting these adjusts scale not bounds and getting these uses the bounds dimension times the scale
@@ -11097,6 +11149,46 @@ zim.Bitmap = function(image, width, height, left, top, scale, style, group, inhe
11097
11149
  return this;
11098
11150
  }
11099
11151
 
11152
+ this.addBitmapData = function() {
11153
+ if (!createjs.BitmapData) {
11154
+ zogy("zim.Bitmap addBitmapData() needs CreatejS 1.5.0 or greater"); return that;
11155
+ }
11156
+ var cc = that.cacheCanvas?that.cacheCanvas:that.cache().cacheCanvas;
11157
+ var bitmapData = new createjs.BitmapData(cc);
11158
+ var bbd = new zim.Bitmap(bitmapData.canvas);
11159
+ bbd.bitmapData = bitmapData;
11160
+ return bbd;
11161
+ }
11162
+
11163
+ this.color = function(color, thresholdColor, x, y) {
11164
+ if (!that.stage) return;
11165
+ if (!that.bitmapData) {
11166
+ zogy("zim.Bitmap must be made with addBitmapData() to use color()"); return that;
11167
+ }
11168
+ if (zot(color)) color = red;
11169
+ color = zik(color);
11170
+ if (zot(thresholdColor)) thresholdColor = dark;
11171
+ var F = that.stage.frame?that.stage.frame:zdf;
11172
+ // convert our mouse point to a point on the bitmap
11173
+ var point;
11174
+ if (x!=null && y!=null) {
11175
+ point = {x:x, y:y};
11176
+ } else {
11177
+ point = that.globalToLocal(F.mouseX, F.mouseY);
11178
+ }
11179
+ // avoid pressing on the same color or the border color
11180
+ var currentColor = this.bitmapData.getPixel(point.x, point.y);
11181
+ if (
11182
+ currentColor == zim.convertColor(color, 'hexnumber') ||
11183
+ currentColor < zim.convertColor(thresholdColor, "hexnumber") // towards black
11184
+ ) return;
11185
+ // get the colorPicker color as hexstring - needed for floodFill
11186
+ var newColor = zim.convertColor(color, 'hexstring');
11187
+ // do a floodFill from the point with the new color
11188
+ that.bitmapData.floodFill(point.x, point.y, newColor);
11189
+ return that;
11190
+ }
11191
+
11100
11192
  zim.displayBase(that);
11101
11193
 
11102
11194
  if (style!==false) zim.styleTransforms(this, DS); // global function - would have put on DisplayObject if had access to it
@@ -12018,8 +12110,12 @@ animationend, change, added, click, dblclick, mousedown, mouseout, mouseover, pr
12018
12110
  var a = that.animations[label];
12019
12111
  processAnimation(a);
12020
12112
  }
12021
- function processAnimation(a) {
12113
+ function processAnimation(a) {
12022
12114
  if (Array.isArray(a)) {
12115
+ if (a.length==1) {
12116
+ processAnimation(a[0]);
12117
+ return;
12118
+ }
12023
12119
  processArray(a);
12024
12120
  } else if (a.constructor == {}.constructor) {
12025
12121
  processObject(a);
@@ -12084,6 +12180,8 @@ animationend, change, added, click, dblclick, mousedown, mouseout, mouseover, pr
12084
12180
  var sig = "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, frame, tweek, id, globalControl, pauseOnBlur";
12085
12181
  var duo; if (duo = zob(that.run, arguments, sig)) return duo;
12086
12182
 
12183
+ if (that.running) that.stopAnimate(that.id); // ZIM 017 - moved this up so single frame stops previous animation
12184
+
12087
12185
  var timeType = getTIME();
12088
12186
 
12089
12187
  var obj;
@@ -12097,8 +12195,10 @@ animationend, change, added, click, dblclick, mousedown, mouseout, mouseover, pr
12097
12195
  return that; // just go to the frame ZIM 017
12098
12196
  }
12099
12197
 
12198
+ that.running = true; // not calling a single frame a run - as it does not animate - ZIM 017
12199
+
12100
12200
  var extraTime;
12101
- if (Array.isArray(label)) {
12201
+ if (Array.isArray(label)) {
12102
12202
  // check labels
12103
12203
  var innerLabel;
12104
12204
  var lastLabel;
@@ -12130,7 +12230,7 @@ animationend, change, added, click, dblclick, mousedown, mouseout, mouseover, pr
12130
12230
  if (endFrame-startFrame > 0) extraTime = tt / (endFrame-startFrame) / 2; // slight cludge - seems to look better?
12131
12231
 
12132
12232
  // if (i==0) firstStartFrame = startFrame;
12133
- }
12233
+ }
12134
12234
  //startFrame = firstStartFrame;
12135
12235
  if (obj.length == 0) return this;
12136
12236
  if (obj.length == 1) { // just one label in list ;-)
@@ -12142,7 +12242,7 @@ animationend, change, added, click, dblclick, mousedown, mouseout, mouseover, pr
12142
12242
  }
12143
12243
  } else { // single label
12144
12244
  setSingle();
12145
- }
12245
+ }
12146
12246
 
12147
12247
  function setSingle() {
12148
12248
  _normalizedFrames = that.parseFrames(label, startFrame, endFrame);
@@ -12153,9 +12253,7 @@ animationend, change, added, click, dblclick, mousedown, mouseout, mouseover, pr
12153
12253
  }
12154
12254
 
12155
12255
  if (zot(time)) time = timeType=="s"?1:1000;
12156
- // if already running the sprite then stop the last run
12157
- if (that.running) that.stopAnimate(that.id);
12158
- that.running = true;
12256
+
12159
12257
 
12160
12258
  if (!Array.isArray(obj)) {
12161
12259
  extraTime = 0;
@@ -16324,7 +16422,7 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
16324
16422
  if (zot(startHead)) startHead = DS.startHead!=null?DS.startHead:null;
16325
16423
  if (zot(endHead)) endHead = DS.endHead!=null?DS.endHead:null;
16326
16424
  if (zot(strokeObj)) strokeObj = DS.strokeObj!=null?DS.strokeObj:{};
16327
-
16425
+
16328
16426
  if (zot(lineType)) lineType = DS.lineType!=null?DS.lineType:"straight";
16329
16427
  if (lineType !== "corner" && lineType != "curve") lineType = "straight";
16330
16428
  if (zot(lineOrientation)) lineOrientation = DS.lineOrientation!=null?DS.lineOrientation:"auto";
@@ -16402,6 +16500,7 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
16402
16500
  }
16403
16501
  var startArrowGuide;
16404
16502
  var endArrowGuide;
16503
+
16405
16504
  if (that._points) {
16406
16505
  var start = that._points[0];
16407
16506
  that._startX = start[0];
@@ -16492,6 +16591,7 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
16492
16591
  if (endHead && endHead.type == "Triangle") endHead.regY = endHead.startRegY;
16493
16592
  }
16494
16593
  }
16594
+
16495
16595
 
16496
16596
  if (that.lineType == "straight") {
16497
16597
  g.mt(sX, sY).lt(eX, eY);
@@ -23795,7 +23895,7 @@ zim.extend(zim.LabelOnArc, zim.Container, "clone", "zimContainer", false);
23795
23895
  //-54.55
23796
23896
 
23797
23897
  /*--
23798
- zim.LabelLetters = function(label, align, valign, letterSpacing, letterSpacings, lineSpacing, lineSpacings, lineHeight, lineAlign, lineValign, cache, rtl, style, group, inherit)
23898
+ zim.LabelLetters = function(label, align, valign, letterSpacing, letterSpacings, lineSpacing, lineSpacings, lineHeight, lineAlign, lineValign, cache, rtl, lineWidth, style, group, inherit)
23799
23899
 
23800
23900
  LabelLetters
23801
23901
  zim class - extends a zim.Container which extends a createjs.Container
@@ -23843,6 +23943,7 @@ label - (default "Label Letters") a String or a ZIM Label
23843
23943
  <i>italic</i> - or <em>italic</em>
23844
23944
  <u>underline</u> - can use this with <a> to make a classic underlined link
23845
23945
  <a href=url target=_blank>link</a>
23946
+ <br> - for a break or use \n
23846
23947
  <font
23847
23948
  color=zimColor
23848
23949
  backgroundColor='htmlColor'
@@ -23873,6 +23974,7 @@ lineAlign - (default LEFT or RIGHT for rtl:true) the horizontal alignment of lin
23873
23974
  lineValign - (default BOTTOM) the vertical alignment within lineSpacing if multiple lines - set to TOP, CENTER/MIDDLE, BOTTOM
23874
23975
  cache - (default false) set to true to cache each letter - improves performance on animation
23875
23976
  rtl - (default false) set to true to reverse letters other than a-zA-Z0-9 and set default lineAlign to RIGHT
23977
+ lineWidth - (default null) set the line width - could cause wrapping. Also see lineWidth property
23876
23978
  style - (default true) set to false to ignore styles set with the STYLE - will receive original parameter defaults
23877
23979
  group - (default null) set to String (or comma delimited String) so STYLE can set default styles to the group(s) (like a CSS class)
23878
23980
  inherit - (default null) used internally but can receive an {} of styles directly
@@ -23897,6 +23999,7 @@ type - the name of the class as a String
23897
23999
  text - get or set the text
23898
24000
  labels - an array of ZIM Label objects for the letters
23899
24001
  numLetters - how many letters (same as numChildren)
24002
+ lineWidth - get or set the line width - could cause wrapping
23900
24003
 
23901
24004
  ALSO: see ZIM Container for properties such as:
23902
24005
  width, height, widthOnly, heightOnly, draggable, level, depth, group
@@ -23911,8 +24014,8 @@ See the CreateJS Easel Docs for Container events such as:
23911
24014
  added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmove, pressup, removed, rollout, rollover
23912
24015
  --*///+54.57
23913
24016
 
23914
- zim.LabelLetters = function(label, align, valign, letterSpacing, letterSpacings, lineSpacing, lineSpacings, lineHeight, lineAlign, lineValign, cache, rtl, style, group, inherit) {
23915
- var sig = "label, align, valign, letterSpacing, letterSpacings, lineSpacing, lineSpacings, lineHeight, lineAlign, lineValign, cache, rtl, style, group, inherit";
24017
+ zim.LabelLetters = function(label, align, valign, letterSpacing, letterSpacings, lineSpacing, lineSpacings, lineHeight, lineAlign, lineValign, cache, rtl, lineWidth, style, group, inherit) {
24018
+ var sig = "label, align, valign, letterSpacing, letterSpacings, lineSpacing, lineSpacings, lineHeight, lineAlign, lineValign, cache, rtl, lineWidth, style, group, inherit";
23916
24019
  var duo; if (duo = zob(zim.LabelLetters, arguments, sig, this)) return duo;
23917
24020
  z_d("54.57");
23918
24021
 
@@ -23930,6 +24033,7 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
23930
24033
  if (zot(rtl)) rtl = DS.rtl != null ? DS.rtl : false;
23931
24034
  if (zot(lineAlign)) lineAlign = DS.lineAlign != null ? DS.lineAlign : rtl?"right":"left";
23932
24035
  if (zot(lineValign)) lineValign = DS.lineValign != null ? DS.lineValign : "bottom";
24036
+ if (zot(lineWidth)) lineWidth = DS.lineWidth != null ? DS.lineWidth : "bottom";
23933
24037
  if (zot(cache)) cache = DS.cache != null ? DS.cache : false;
23934
24038
 
23935
24039
  this.zimContainer_constructor(null, null, null, null, false);
@@ -23974,28 +24078,28 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
23974
24078
  // html = "!Roger הגיע בשבילך משהו בדואר Dan אני לומד עברית";
23975
24079
  // html = "הגיע בשבילך משהו בדואר.";
23976
24080
 
23977
- function insert(data) {
23978
- return data.split("").reverse().join("")
23979
- }
23980
- if (rtl) {
23981
- count = -1;
23982
- html = html.replace(/[\u0591-\u07FF]+/ig, insert);
24081
+ // function insert(data) {
24082
+ // return data.split("").reverse().join("")
24083
+ // }
24084
+ // if (rtl) {
24085
+ // count = -1;
24086
+ // html = html.replace(/[\u0591-\u07FF]+/ig, insert);
23983
24087
 
23984
- // and there may be tags or LTR characters next to RTL without a space:
23985
- html = html.replace(/([^\u0591-\u07FF ])([\u0591-\u07FF])/ig, "$1-!!-$2"); // note the not space
23986
- html = html.replace(/([\u0591-\u07FF])([^\u0591-\u07FF ])/ig, "$1-!!-$2"); // note the not space
23987
- html = html.replace(/([^\u0591-\u07FF]) ([\u0591-\u07FF])/ig, "$1-!!- -!!-$2");
23988
- html = html.replace(/([\u0591-\u07FF]) ([^\u0591-\u07FF])/ig, "$1-!!- -!!-$2");
24088
+ // // and there may be tags or LTR characters next to RTL without a space:
24089
+ // html = html.replace(/([^\u0591-\u07FF ])([\u0591-\u07FF])/ig, "$1-!!-$2"); // note the not space
24090
+ // html = html.replace(/([\u0591-\u07FF])([^\u0591-\u07FF ])/ig, "$1-!!-$2"); // note the not space
24091
+ // html = html.replace(/([^\u0591-\u07FF]) ([\u0591-\u07FF])/ig, "$1-!!- -!!-$2");
24092
+ // html = html.replace(/([\u0591-\u07FF]) ([^\u0591-\u07FF])/ig, "$1-!!- -!!-$2");
23989
24093
 
23990
- var sp = html.split(/-!!-/g);
23991
- zim.loop(sp, function(ssp, i){
23992
- if (ssp.match(/[\u0591-\u07FF]/i)) {
23993
- sp[i] = ssp.split(" ").reverse().join(" ");
23994
- }
23995
- });
23996
- html = sp.join("");
23997
- }
23998
-
24094
+ // var sp = html.split(/-!!-/g);
24095
+ // zim.loop(sp, function(ssp, i){
24096
+ // if (ssp.match(/[\u0591-\u07FF]/i)) {
24097
+ // sp[i] = ssp.split(" ").reverse().join(" ");
24098
+ // }
24099
+ // });
24100
+ // html = sp.join("");
24101
+ // }
24102
+
23999
24103
 
24000
24104
  // normalize tags
24001
24105
  html = html.replace(/\n|\r/g,"<br>");
@@ -24091,7 +24195,9 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
24091
24195
  // b,i,u,br,a,font
24092
24196
  // var da = [,, [["b","i"]] ,[,["b"]],,,[["br","font color=red size=10 family=courier"]],["i"]],...];
24093
24197
  return {text:p, data:data, original:original};
24094
- }
24198
+
24199
+ } // end parse html
24200
+
24095
24201
 
24096
24202
  that.numLetters = label.text.length;
24097
24203
 
@@ -24310,6 +24416,21 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
24310
24416
  }
24311
24417
 
24312
24418
  lineW += letter.width + s;
24419
+
24420
+ // if (lineW > lineWidth && letter.text == " ") {
24421
+ // lineY += (zot(lineHeight)?lineH:lineHeight) + lineSpacings[lineNum];
24422
+ // linePositionsY.push(lineY);
24423
+ // lineHeights.push(zot(lineHeight)?lineH:lineHeight);
24424
+ // lineWidths.push(lineW);
24425
+ // maxW = Math.max(maxW, lineW);
24426
+ // lineH = 0;
24427
+ // lineW = 0;
24428
+ // that.lines.push([]);
24429
+ // lineNum++;
24430
+ // letter.dispose();
24431
+ // continue;
24432
+ // }
24433
+
24313
24434
  lineH = Math.max(lineH, letter.height);
24314
24435
 
24315
24436
  if (i==that.numLetters-1) {
@@ -24328,52 +24449,203 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
24328
24449
 
24329
24450
 
24330
24451
  // LOOP THROUGH LINES AND APPLY POSITIONS
24331
- var count = 0;
24332
- for (var j=0; j<that.lines.length; j++) {
24333
- var ll = that.lines[j];
24334
- lineW = lineWidths[j];
24335
- lineH = lineHeights[j];
24336
- lineY = linePositionsY[j];
24452
+ function doPositions(second) {
24453
+ var count = 0;
24454
+ for (var j=0; j<that.lines.length; j++) {
24455
+ var ll = that.lines[j];
24456
+ if (rtl) ll.reverse(); // ZIM 017 PATCH
24457
+ lineW = lineWidths[j];
24458
+ lineH = lineHeights[j];
24459
+ lineY = linePositionsY[j];
24460
+
24461
+ var startX, startY;
24462
+ if (lineAlign=="left" || (lineWidth>0 && !second)) startX = 0; // if lineWidth first time just measuring
24463
+ else if (lineAlign=="right") startX = maxW-lineW;
24464
+ else startX = (maxW-lineW)/2;
24465
+ startY = lineY;
24466
+
24467
+ for (i=0; i<ll.length; i++) {
24468
+ count++;
24469
+ if (cache) letter.cache();
24470
+ letter = ll[i];
24471
+ letter.regX = (align=="left")?0:(align=="right"?letter.width:letter.width/2);
24472
+ letter.regY = valign=="top"?0:(valign=="bottom"?letter.height:letter.height/2);
24473
+
24474
+ var sY = startY+(valign=="top"?0:valign=="bottom"?letter.height:letter.height/2);
24475
+ if (lineValign=="center" || lineValign=="middle") {
24476
+ sY += (lineHeights[j]-letter.height)/2;
24477
+ } else if (lineValign=="bottom") {
24478
+ sY += lineHeights[j]-letter.height;
24479
+ }
24480
+ s = letterSpacingsOriginal?letterSpacings[count-1]:zot(letter.backgroundColor)?letterSpacings[count-1]:-.5;
24481
+ if (align=="left") {
24482
+ letter.loc(startX, sY, that);
24483
+ startX = letter.x+letter.width+s;
24484
+ } else if (align=="right") {
24485
+ letter.loc(startX+letter.width, sY, that);
24486
+ startX = letter.x+s;
24487
+ } else {
24488
+ letter.loc(startX+letter.width/2, sY, that);
24489
+ startX = letter.x+letter.width/2+s;
24490
+ }
24491
+
24492
+ } // end lines letters
24337
24493
 
24338
- var startX, startY;
24339
- if (lineAlign=="left") startX = 0;
24340
- else if (lineAlign=="right") startX = maxW-lineW;
24341
- else startX = (maxW-lineW)/2;
24342
- startY = lineY;
24343
-
24344
- for (i=0; i<ll.length; i++) {
24345
- count++;
24346
- if (cache) letter.cache();
24347
- letter = ll[i];
24348
- letter.regX = align=="left"?0:(align=="right"?letter.width:letter.width/2);
24349
- letter.regY = valign=="top"?0:(valign=="bottom"?letter.height:letter.height/2);
24350
-
24351
- var sY = startY+(valign=="top"?0:valign=="bottom"?letter.height:letter.height/2);
24352
- if (lineValign=="center" || lineValign=="middle") {
24353
- sY += (lineHeights[j]-letter.height)/2;
24354
- } else if (lineValign=="bottom") {
24355
- sY += lineHeights[j]-letter.height;
24494
+
24495
+ } // end lines
24496
+ }
24497
+ doPositions();
24498
+
24499
+
24500
+ if (lineWidth > 0) {
24501
+ var lines = [];
24502
+ var letters = [];
24503
+ var lastSpace;
24504
+ var row = 0;
24505
+
24506
+ if (rtl) {
24507
+
24508
+ for (var j=0; j<that.lines.length; j++) {
24509
+ var list = that.lines[j];
24510
+ var count = 0;
24511
+ var back = 0;
24512
+ lines[row] = [];
24513
+ letters[row] = [];
24514
+ lastSpace = null;
24515
+
24516
+ var startX = list[list.length-1].x;
24517
+
24518
+ for (var i=list.length-1; i>=0; i--) {
24519
+ var letter = list[i];
24520
+ letter.mov(back);
24521
+ lines[row].push(letter);
24522
+ letters[row].push(letter.text)
24523
+ if (startX-letter.x > lineWidth) {
24524
+ if (letter.text == " ") {
24525
+ lines[row].pop();
24526
+ letters[row].pop();
24527
+ row++;
24528
+ back += letter.x+letterSpacing;
24529
+ letter.dispose();
24530
+ lines[row] = [];
24531
+ letters[row] = [];
24532
+ lastSpace = null;
24533
+ count = -1;
24534
+ } else if (lastSpace > 0) {
24535
+ var move = lines[row].splice(lastSpace);
24536
+ var move2 = letters[row].splice(lastSpace);
24537
+ row++;
24538
+ var space = move.shift(); // remove space from start
24539
+ move2.shift();
24540
+ for (var k=0; k<move.length; k++) {
24541
+ move[k].mov(startX-space.x-letterSpacing);
24542
+ }
24543
+ back += startX-(space.x+letterSpacing);
24544
+ space.dispose();
24545
+ lines[row] = move;
24546
+ letters[row] = move2;
24547
+ lastSpace = null;
24548
+ count = lines[row].length-1;
24549
+ }
24550
+ }
24551
+ if (letter.text == " ") lastSpace = count;
24552
+ count++;
24553
+ }
24554
+ row++
24356
24555
  }
24357
- s = letterSpacingsOriginal?letterSpacings[count-1]:zot(letter.backgroundColor)?letterSpacings[count-1]:-.5;
24358
- if (align=="left") {
24359
- letter.loc(startX, sY, that);
24360
- startX = letter.x+letter.width+s;
24361
- } else if (align=="right") {
24362
- letter.loc(startX+letter.width, sY, that);
24363
- startX = letter.x+s;
24364
- } else {
24365
- letter.loc(startX+letter.width/2, sY, that);
24366
- startX = letter.x+letter.width/2+s;
24556
+
24557
+
24558
+ } else {
24559
+
24560
+ for (var j=0; j<that.lines.length; j++) {
24561
+ var list = that.lines[j];
24562
+ var count = 0;
24563
+ var back = 0;
24564
+ lines[row] = [];
24565
+ letters[row] = [];
24566
+ lastSpace = null;
24567
+ for (var i=0; i<list.length; i++) {
24568
+ var letter = list[i];
24569
+ letter.mov(-back);
24570
+ lines[row].push(letter);
24571
+ letters[row].push(letter.text)
24572
+ if (letter.x + letter.width > lineWidth) {
24573
+ if (letter.text == " ") {
24574
+ lines[row].pop();
24575
+ letters[row].pop();
24576
+ row++;
24577
+ back += letter.x+letterSpacing;
24578
+ letter.dispose();
24579
+ lines[row] = [];
24580
+ letters[row] = [];
24581
+ lastSpace = null;
24582
+ count = -1;
24583
+ } else if (lastSpace > 0) {
24584
+ var move = lines[row].splice(lastSpace);
24585
+ var move2 = letters[row].splice(lastSpace);
24586
+ row++;
24587
+ var space = move.shift(); // remove space from start
24588
+ move2.shift();
24589
+ for (var k=0; k<move.length; k++) {
24590
+ move[k].mov(-space.x-letterSpacing);
24591
+ }
24592
+ back += space.x+letterSpacing;
24593
+ space.dispose();
24594
+ lines[row] = move;
24595
+ letters[row] = move2;
24596
+ lastSpace = null;
24597
+ count = lines[row].length-1;
24598
+ }
24599
+ }
24600
+ if (letter.text == " ") lastSpace = count;
24601
+ count++;
24602
+ }
24603
+ row++
24367
24604
  }
24368
-
24369
- } // end lines letters
24370
- } // end lines
24605
+
24606
+ }
24607
+
24608
+
24609
+ that.lines = lines;
24610
+ lineWidths = [];
24611
+ lineHeights = [];
24612
+ linePositionsY = [];
24613
+ maxW = lineWidth;
24614
+
24615
+ var currentHeight = 0;
24616
+ var lastMaxHeight = 0;
24617
+
24618
+ for (j=0; j<that.lines.length; j++) {
24619
+ var maxHeight = 0;
24620
+ var totalW = 0;
24621
+ var list = that.lines[j];
24622
+ for (i=0; i<list.length; i++) {
24623
+ var letter = list[i];
24624
+ totalW += letter.width + letterSpacing;
24625
+ if (letter.height > maxHeight) maxHeight = letter.height;
24626
+ }
24627
+ if (list.length==0) maxHeight = lastMaxHeight;
24628
+ lineWidths[j] = totalW-letterSpacing;
24629
+ lineHeights[j] = maxHeight;
24630
+ linePositionsY[j] = currentHeight;
24631
+ currentHeight += maxHeight + lineSpacing;
24632
+ lastMaxHeight = maxHeight;
24633
+ totalW = 0;
24634
+ }
24635
+
24636
+ doPositions(true); // second time for real
24637
+
24638
+
24639
+ } // end line width
24371
24640
 
24372
- if (!that.getBounds()) that.setBounds(0,0,0,0);
24373
- that.regX = that.getBounds().x;
24374
- that.regY = that.getBounds().y;
24641
+ var bou = that.getBounds();
24642
+ if (!bou) that.setBounds(0,0,0,0);
24643
+ if (lineWidth>0) that.setBounds(0,0,lineWidth,bou.height);
24644
+ bou = that.getBounds();
24645
+ that.regX = bou.x;
24646
+ that.regY = bou.y;
24375
24647
 
24376
- }
24648
+ } // end make
24377
24649
 
24378
24650
  make();
24379
24651
 
@@ -24423,6 +24695,16 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
24423
24695
  }
24424
24696
  });
24425
24697
 
24698
+ Object.defineProperty(this, 'lineWidth', {
24699
+ get: function () {
24700
+ return lineWidth;
24701
+ },
24702
+ set: function (value) {
24703
+ lineWidth = value;
24704
+ make();
24705
+ }
24706
+ });
24707
+
24426
24708
  this.dispose = function() {
24427
24709
  zim.gD(this); // globalDispose function for common elements
24428
24710
  zim.loop(that.labels, function (letter) {
@@ -24434,7 +24716,7 @@ added, click, dblclick, mousedown, mouseout, mouseover, pressdown (ZIM), pressmo
24434
24716
 
24435
24717
  if (style!==false) zim.styleTransforms(this, DS);
24436
24718
  this.clone = function () {
24437
- return that.cloneProps(new zim.LabelLetters(label, align, valign, letterSpacing, letterSpacings, lineSpacing, lineSpacings, lineHeight, lineAlign, lineValign, cache, rtl, style, this.group, inherit));
24719
+ return that.cloneProps(new zim.LabelLetters(label, align, valign, letterSpacing, letterSpacings, lineSpacing, lineSpacings, lineHeight, lineAlign, lineValign, cache, rtl, lineWidth, style, this.group, inherit));
24438
24720
  };
24439
24721
 
24440
24722
  };
@@ -47060,16 +47342,16 @@ This is so ZIM does not have to keep track of HTML tags each time a container is
47060
47342
  NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
47061
47343
 
47062
47344
  EXAMPLE
47345
+ // loading a single pic
47063
47346
  const loader = new Loader({
47064
- label:"UPLOAD PIC OR DROP PICS HERE",
47347
+ label:"UPLOAD PIC HERE",
47065
47348
  width:700,
47066
47349
  height:400,
47067
- corner:50
47350
+ corner:50,
47351
+ multiple:false // or don't bother and it just gets the first loaded
47068
47352
  }).center();
47069
47353
  loader.on("loaded", e=>{
47070
- loop(e.bitmaps, bitmap=>{
47071
- bitmap.centerReg().drag();
47072
- });
47354
+ e.bitmap.centerReg().drag();
47073
47355
  loader.removeFrom();
47074
47356
  S.update();
47075
47357
  });
@@ -47079,7 +47361,24 @@ const saveButton = new Button({label:"SAVE"})
47079
47361
  .pos(10,10,RIGHT,BOTTOM)
47080
47362
  .tap(()=>{
47081
47363
  loader.save(S); // or some other container... can specify crop bounds too
47082
- }
47364
+ });
47365
+ END EXAMPLE
47366
+
47367
+ EXAMPLE
47368
+ // loading multiple pics
47369
+ const loader = new Loader({
47370
+ label:"UPLOAD PIC OR DROP PICS HERE",
47371
+ width:700,
47372
+ height:400,
47373
+ corner:50
47374
+ }).center();
47375
+ loader.on("loaded", e=>{
47376
+ loop(e.bitmaps, bitmap=>{
47377
+ bitmap.centerReg().drag();
47378
+ });
47379
+ loader.removeFrom();
47380
+ S.update();
47381
+ });
47083
47382
  END EXAMPLE
47084
47383
 
47085
47384
  EXAMPLE
@@ -54783,7 +55082,9 @@ END EXAMPLE
54783
55082
 
54784
55083
  EXAMPLE
54785
55084
  const physics = new Physics().drag();
54786
- const points = [ // fish shape
55085
+ // fish shape
55086
+ // make sure points are clockwise in order - if counterClockwise then use myBlob.reversePoints()
55087
+ const points = [
54787
55088
  [0.5,-29.2,0,0,-79.1,25.5,79.1,-25.5,"mirror"],[182.3,15.9,0,0,-33.9,-59.6,-31.1,55.6,"free"],
54788
55089
  [15.4,86.2,0,0,67,10.4,-67,-10.4,"mirror"],[-163.6,73.2,0,0,67.9,-49.9,10.7,-51.8,"free"],
54789
55090
  [-165.7,-43.9,0,0,11.9,40.8,70.1,43.6,"free"]
@@ -54808,7 +55109,8 @@ shape - (default object shape) - "rectangle" for any object other than Circle, D
54808
55109
  but can specify a "circle" for a Sprite or Bitmap, for instance - to try and match shape
54809
55110
  custom polygon bodies can also be made with manual Box2D and then use physics.addMap()
54810
55111
  but the only shapes available automatically are "rectangle", "circle", "triangle"
54811
- Note - addPhysics() can be placed on a ZIM Blob as well
55112
+ Note - addPhysics() can be placed on a ZIM Blob as well - see Physics.validate() for more details
55113
+ such as the Blob must have clockwise points - if counterClockwise then use myBlob.reversePoints()
54812
55114
  friction - (default .8) - how sticky will the body act - set to 0 to slide.
54813
55115
  linear - (default .5) - linear damping which slows the movement - set to 0 for no damping
54814
55116
  angular - (default .5) - angular damping which slows the rotation - set to 0 for no damping
@@ -62013,6 +62315,9 @@ See https://zimjs.com/cat/page.html
62013
62315
  ZIM Cat 03 intruduces the ZIM Arrow() class for an easy previous/next button system.
62014
62316
  See https://zimjs.com/survey.html
62015
62317
 
62318
+ ZIM 017 added continuous pages
62319
+ See https://zimjs.com/017/continuous.html
62320
+
62016
62321
  As of ZIM ZIM 02 a GlobalManager will be added to handle Pages resize for cached transitions.
62017
62322
 
62018
62323
  NOTE: if you have a TextArea, Tag or Loader on a page, ZIM will automatically add and remove it.
@@ -88825,6 +89130,23 @@ new Tile(new SVG("file.svg", 100, 100), 4, 4)).center();
88825
89130
  // would be better to preload - see next example
88826
89131
  END EXAMPLE
88827
89132
 
89133
+ EXAMPLE
89134
+ // Adding Physics to an SVG
89135
+ // Must import zim_physics or have Physics checked in the Editor
89136
+ // cannot make a Bitmap until SVG is made:
89137
+ const physics = new Physics();
89138
+ const svg = new SVG("file.svg");
89139
+ svg.on("complete", ()=>{
89140
+ const bitmap = new Bitmap(svg).center();
89141
+ const blob = new Blob({
89142
+ points:simplifyPoints(outlineImage(bitmap), 10),
89143
+ color:faint,
89144
+ interactive:false
89145
+ }).loc(bitmap).addPhysics();
89146
+ bitmap.addTo(blob);
89147
+ });
89148
+ END EXAMPLE
89149
+
88828
89150
  EXAMPLE
88829
89151
  // pre-load and Tile an SVG
88830
89152
  new Frame(FIT, 1024, 768, light, grey, ready, "file.svg", "assets/");
@@ -89174,7 +89496,7 @@ dispatches "result" when either as each word is spoken if listen() is used (inte
89174
89496
  Note: iOS (at this time) does not support the listen() and result event
89175
89497
  dispatches "speechend" events when listen() has detected an end to the talking
89176
89498
  dispatches an "error" event if no words are spoken, etc. the event object has an error property with the error message
89177
- dispatches "start", "end" and "error" on the utterance object returned by talk()
89499
+ dispatches "start", "end", "boundary", and "error" on the utterance object returned by talk()
89178
89500
  Note: there are more features to the Web Speech API - see the HTML docs
89179
89501
  --*///+83.095
89180
89502
  zim.Speech = function() {
@@ -89241,6 +89563,7 @@ dispatches "start", "end" and "error" on the utterance object returned by talk()
89241
89563
  var utter = new SpeechSynthesisUtterance();
89242
89564
  utter.addEventListener("start", function(e) {that.dispatchEvent(e);});
89243
89565
  utter.addEventListener("end", function(e) {that.dispatchEvent(e);});
89566
+ utter.addEventListener("boundary", function(e) {that.dispatchEvent(e);});
89244
89567
  utter.addEventListener("error", function(e) {that.dispatchEvent(e);});
89245
89568
 
89246
89569
  if (voice && typeof voice == "string" && that.voiceLookup) voice = that.voiceLookup[voice];
@@ -89375,7 +89698,7 @@ In ZIM 014 we added a keyboardMessage() method to prompt for an interaction so k
89375
89698
  Also see ZIM Keyboard(), TextEditor(), TextInput() and MotionController() for various keyboard functionality.
89376
89699
 
89377
89700
  EXAMPLE
89378
- keyboardMessage(); // will prompt for keyboard control
89701
+ F.keyboardMessage(); // will prompt for keyboard control
89379
89702
  F.on("keydown", e=>{
89380
89703
  zog(e.key) // a string of the keypress
89381
89704
  zog(e.keyCode) // the numeric code of the keypress (older but used in lots of examples)
@@ -89436,51 +89759,56 @@ DESCRIPTION
89436
89759
  The Frame has a "devicemotion" event to capture device tilt
89437
89760
  and a "deviceorientation" to capture device rotation (like a compass)
89438
89761
 
89439
- Also see the PermissionAsk() class which will handle asking for permission on iOS devices.
89762
+ Also see the PermissionAsk() class which will handle asking for permission.
89440
89763
 
89441
89764
  NOTE:
89442
89765
  For either event the Frame sensors parameter MUST be set to true
89443
89766
 
89444
89767
  EXAMPLE
89445
- // for capturing tilt on device (rotation about an axis)
89446
- // also SEE the PermissionAsk example below
89447
- // also set Frame sensors parameter to true
89448
- // and be on a mobile device
89449
- const label = new Label().center();
89450
- F.on("deviceorientation", e=>{
89451
- label.text = e.rotation.x +","+ e.rotation.y +","+ e.rotation.z;
89452
- S.update();
89453
- });
89454
- END EXAMPLE
89768
+ // DEVICE ORIENTATION - gives angle of device in all 3 dimensions
89769
+ // Note: this is NOT an orientation event to see if phone is portrait or landscape (see Frame orientation event)
89770
+ // Note: must set Frame() sensors true - for example:
89771
+ // new Frame({scaling:FIT, width:1024, height:768, color:white, outerColor:dark, ready:ready, sensors:true});
89455
89772
 
89456
- EXAMPLE
89457
- // on iOS, the sensors must be allowed first - this example works for all devices
89458
- const permissionType = "deviceorientation"; // or "devicemotion"
89773
+ const permissionType = "deviceorientation";
89459
89774
  const ask = new PermissionAsk(init, permissionType);
89460
- function init(yes) {
89461
- // if the user answers yes to the PermissionAsk
89462
- const errorPane = new Pane("SENSOR not available",yellow);
89463
- if (yes) {
89464
- // use the sensors
89465
- label.text = decimals(e.rotation.x) +","+ decimals(e.rotation.y) +","+ decimals(e.rotation.z);
89466
- S.update();
89467
- } else { // answered no to PermissionAsk dialog
89775
+ function init(yes) {
89776
+ const errorPane = new Pane("SENSOR not available",yellow);
89777
+ if (yes) { // the user answers yes to the PermissionAsk
89778
+ // use the sensors
89779
+ const label = new Label("test on mobile").centerReg();
89780
+ F.on("deviceorientation", e=>{
89781
+ // use the sensors
89782
+ label.text = label.text = "x: "+decimals(e.rotation.x) +"\ny: "+ decimals(e.rotation.y) +"\nz: "+ decimals(e.rotation.z);
89783
+ S.update();
89784
+ });
89785
+ } else { // the user answered no to PermissionAsk dialog
89468
89786
  errorPane.show();
89469
89787
  }
89470
89788
  }
89471
89789
  END EXAMPLE
89472
89790
 
89473
89791
  EXAMPLE
89474
- // for shaking motion - ALSO see the PermissionAsk example above for iOS
89475
- // and replace "deviceorientation" with "devicemotion"
89476
- // and replace e.rotation.x, etc. with e.acceleration.x etc.
89477
- // also set Frame sensors parameter to true
89478
- // and be on a mobile device
89479
- const label = new Label().center();
89480
- F.on("devicemotion", e=>{
89481
- label.text = e.acceleration.x +","+ e.acceleration.y +","+ e.acceleration.z;
89482
- S.update();
89483
- });
89792
+ // DEVICE MOTION - gives accelerometer values in all 3 dimensions
89793
+ // Note: must set Frame() sensors true - for example:
89794
+ // new Frame({scaling:FIT, width:1024, height:768, color:white, outerColor:dark, ready:ready, sensors:true});
89795
+
89796
+ const permissionType = "devicemotion";
89797
+ const ask = new PermissionAsk(init, permissionType);
89798
+ function init(yes) {
89799
+ const errorPane = new Pane("SENSOR not available",yellow);
89800
+ if (yes) { // the user answers yes to the PermissionAsk
89801
+ // use the sensors
89802
+ const label = new Label("test on mobile").centerReg();
89803
+ F.on("devicemotion", e=>{
89804
+ // use the sensors
89805
+ label.text = "x: "+decimals(e.acceleration.x, 3) +"\ny: "+ decimals(e.acceleration.y, 3) +"\nz: "+ decimals(e.acceleration.z, 3);
89806
+ S.update();
89807
+ });
89808
+ } else { // the user answered no to PermissionAsk dialog
89809
+ errorPane.show();
89810
+ }
89811
+ }
89484
89812
  END EXAMPLE
89485
89813
 
89486
89814
  EVENTS
@@ -89510,30 +89838,59 @@ This is for iOS only - if not in iOS then will just pass through the test.
89510
89838
 
89511
89839
  NOTE: this started as SensorAsk but the class has been adjusted to handle other permissions and the name has been changed in ZIM 016
89512
89840
 
89841
+ NOTE: for deviceorientation and devicemotion the Frame sensors parameter must be set to true
89842
+
89513
89843
  NOTE: as of ZIM 5.5.0 the zim namespace is no longer required (unless zns is set to true before running zim)
89514
89844
 
89515
89845
  EXAMPLE
89516
- // on iOS, the sensors must be allowed first
89517
- const permissionType = "deviceorientation"; // or "devicemotion"
89846
+ // DEVICE ORIENTATION - gives angle of device in all 3 dimensions
89847
+ // Note: this is NOT an orientation event to see if phone is portrait or landscape (see Frame orientation event)
89848
+ // Note: must set Frame() sensors true - for example:
89849
+ // new Frame({scaling:FIT, width:1024, height:768, color:white, outerColor:dark, ready:ready, sensors:true});
89850
+
89851
+ const permissionType = "deviceorientation";
89518
89852
  const ask = new PermissionAsk(init, permissionType);
89519
- function init(yes) {
89520
- // if the user answers yes to the PermissionAsk
89521
- const errorPane = new Pane("SENSOR not available",yellow);
89522
- if (yes) {
89853
+ function init(yes) {
89854
+ const errorPane = new Pane("SENSOR not available",yellow);
89855
+ if (yes) { // the user answers yes to the PermissionAsk
89523
89856
  // use the sensors
89524
- const label = new Label({text:"test on mobile", align:CENTER}).centerReg();
89857
+ const label = new Label("test on mobile").centerReg();
89858
+ F.on("deviceorientation", e=>{
89859
+ // use the sensors
89860
+ label.text = label.text = "x: "+decimals(e.rotation.x) +"\ny: "+ decimals(e.rotation.y) +"\nz: "+ decimals(e.rotation.z);
89861
+ S.update();
89862
+ });
89863
+ } else { // the user answered no to PermissionAsk dialog
89864
+ errorPane.show();
89865
+ }
89866
+ }
89867
+ END EXAMPLE
89868
+
89869
+ EXAMPLE
89870
+ // DEVICE MOTION - gives accelerometer values in all 3 dimensions
89871
+ // Note: must set Frame() sensors true - for example:
89872
+ // new Frame({scaling:FIT, width:1024, height:768, color:white, outerColor:dark, ready:ready, sensors:true});
89873
+
89874
+ const permissionType = "devicemotion";
89875
+ const ask = new PermissionAsk(init, permissionType);
89876
+ function init(yes) {
89877
+ const errorPane = new Pane("SENSOR not available",yellow);
89878
+ if (yes) { // the user answers yes to the PermissionAsk
89879
+ // use the sensors
89880
+ const label = new Label("test on mobile").centerReg();
89525
89881
  F.on("devicemotion", e=>{
89526
89882
  // use the sensors
89527
- label.text = decimals(e.rotation.x) +","+ decimals(e.rotation.y) +","+ decimals(e.rotation.z);
89883
+ label.text = "x: "+decimals(e.acceleration.x, 3) +"\ny: "+ decimals(e.acceleration.y, 3) +"\nz: "+ decimals(e.acceleration.z, 3);
89528
89884
  S.update();
89529
- })
89530
- } else { // answered no to PermissionAsk dialog
89885
+ });
89886
+ } else { // the user answered no to PermissionAsk dialog
89531
89887
  errorPane.show();
89532
89888
  }
89533
89889
  }
89534
89890
  END EXAMPLE
89535
89891
 
89536
89892
  EXAMPLE
89893
+ // on iOS, the app must be interacted with before using mic or cam
89537
89894
  // goes right to permissions on computer and android
89538
89895
  // pops up a PermissionAsk Pane on iOS then if yes, goes to permissions on iOS
89539
89896
  new PermissionAsk(init, "cam");
@@ -89549,7 +89906,7 @@ EXAMPLE
89549
89906
  // but pops up a PermissionAsk Pane on iOS then if yes, goes to permissions on iOS
89550
89907
  new PermissionAsk(init, "mic"); // or "cam" or "miccam"
89551
89908
  function init(val) {
89552
- zog(val); // media stream if yes to permissions otherwise false
89909
+ new Label(val).center(); // media stream if yes to permissions otherwise false
89553
89910
  S.update();
89554
89911
  }
89555
89912
  END EXAMPLE
@@ -89558,8 +89915,8 @@ PARAMETERS - accepts ZIM DUO regular parameters in order or a configuration obje
89558
89915
  callback - the function to callback when permission is accepted
89559
89916
  if the permissionType is deviceorientation or devicemotion this will receive true for accept or false for no permission
89560
89917
  if the permissionType is audio, video or audiovideo this will receive a stream if accepted or false if not
89561
- for not iOS, the system permissions will appear
89562
- for iOS the PermissionAsk Pane will be shown and the system permissions
89918
+ for not iOS, the system permissions will appear if needed
89919
+ for iOS the PermissionAsk Pane will be shown and then system permissions
89563
89920
  in all cases, the callback will be called on result
89564
89921
  the parameter given to the callback will be true (sensors) or a media stream (mic / cam) or false if not accepted
89565
89922
  permissionType - (default "deviceorientation") the string deviceorientation, devicemotion, mic, cam, or miccam
@@ -89601,7 +89958,7 @@ alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, e
89601
89958
  zim.PermissionAsk = function(callback, permissionType, color, backgroundColor, style, group, inherit) {
89602
89959
  var sig = "callback, permissionType, color, backgroundColor, style, group, inherit";
89603
89960
  var duo; if (duo = zob(zim.PermissionAsk, arguments, sig, this)) return duo;
89604
- z_d("83.01");
89961
+ z_d("83.01");
89605
89962
 
89606
89963
  this.group = group;
89607
89964
  var DS = style===false?{}:zim.getStyle("PermissionAsk", this.group, inherit);
@@ -89626,79 +89983,104 @@ alpha, cursor, shadow, name, mouseChildren, mouseEnabled, parent, numChildren, e
89626
89983
  borderColor:color,
89627
89984
  borderWidth:2
89628
89985
  });
89629
- var pt = permissionType;
89630
- that.yes = new zim.Button({label:"YES", group:"PermissionAsk"}).sca(.65).pos(0,30,CENTER,TOP,this).tap(function() {
89631
- that.hide(true);
89632
- if (pt == "mic" || pt == "cam" || pt == "miccam") {
89633
- if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
89634
- navigator.mediaDevices.getUserMedia({audio: (pt=="mic" || pt=="miccam"), video:(pt=="cam" || pt=="miccam") })
89635
- .then(function(stream) {
89636
- callback(stream);
89637
- })
89638
- .catch(function(err) {
89639
- callback(false);
89640
- });
89641
- } else callback(false);
89642
- } else {
89643
- var s = DeviceMotionEvent;
89644
- if (pt != "devicemotion") s = DeviceOrientationEvent;
89645
- s.requestPermission().then(function(result) {
89646
- if (result != "denied") callback(true);
89647
- else callback(false);
89648
- });
89649
- }
89650
- });
89651
- var words = {deviceorientation:"sensors", devicemotion:"sensors", mic:"mic", cam:"cam", miccam:"mic/cam"};
89986
+ var pt = permissionType;
89987
+ var okay = false;
89988
+ that.yes = new zim.Button({label:"YES", group:"PermissionAsk"}).sca(.65).pos(0,30,CENTER,TOP,this);
89989
+ var words = {deviceorientation:"sensors", devicemotion:"sensors", mic:"mic", cam:"cam", miccam:"mic/cam"};
89652
89990
  that.label = new zim.Label("Use " + (words[pt]?words[pt]:"feature") + "?", 30, null, color, null, null, null, "center").sca(.9).centerReg(this);
89653
- that.no = new zim.Button({label:"NO", group:"PermissionAsk"}).sca(.65).pos(0,30,CENTER,BOTTOM,this).tap(function() {
89654
- that.hide(false);
89655
- callback(false);
89656
- });
89991
+ that.no = new zim.Button({label:"NO", group:"PermissionAsk"}).sca(.65).pos(0,30,CENTER,BOTTOM,this);
89657
89992
 
89658
89993
  new zim.Circle(110, zim.clear, color, 1).center(this).alp(.8);
89659
89994
  new zim.Circle(120, zim.clear, color, 1).center(this).alp(.5);
89660
89995
  new zim.Circle(130, zim.clear, color, 1).center(this).alp(.2);
89661
89996
  if (style!==false) zim.styleTransforms(this, DS);
89662
89997
 
89663
- if (pt == "mic" || pt == "cam" || pt == "miccam") {
89664
- if (M=="ios") {
89665
- that.show();
89666
- return;
89667
- }
89668
- if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
89669
- navigator.mediaDevices.getUserMedia({audio: (pt=="mic" || pt=="miccam"), video:(pt=="cam" || pt=="miccam") })
89670
- .then(function(stream) {
89671
- callback(stream);
89672
- })
89673
- .catch(function(err) {
89674
- callback(false);
89675
- });
89676
- } else callback(false);
89677
- return;
89678
- }
89998
+ var frame = WW.zdf;
89999
+ if (pt == "mic" || pt == "cam" || pt == "miccam") {
90000
+ if (M=="ios") {
90001
+ setPane();
90002
+ return;
90003
+ }
90004
+ if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
90005
+ navigator.mediaDevices.getUserMedia({audio: (pt=="mic" || pt=="miccam"), video:(pt=="cam" || pt=="miccam") })
90006
+ .then(function(stream) {
90007
+ callback(stream);
90008
+ })
90009
+ .catch(function(err) {
90010
+ callback(false);
90011
+ });
90012
+ } else callback(false);
90013
+ return;
90014
+ }
89679
90015
 
89680
- // sensors only
90016
+ // sensors only
89681
90017
  if (typeof DeviceOrientationEvent != "undefined" && DeviceOrientationEvent && typeof DeviceOrientationEvent.requestPermission == "function") {
89682
- that.show();
90018
+ setPane();
89683
90019
  } else {
89684
90020
  var called = false;
89685
90021
  WW.addEventListener(permissionType, testMe);
89686
90022
  // instead of testing for mobile - some laptops like chromebook have sensors so test for a reading
89687
90023
  function testMe(e) {
90024
+ if (okay) return;
89688
90025
  if (permissionType=="deviceorientation") {
89689
90026
  if (e.alpha==null || (e.alpha==0&&e.beta==0&&e.gamma==0)) callback(false);
89690
- else callback(true);
90027
+ else setEvents();
89691
90028
  } else {
89692
- if (!e.acceleration || e.acceleration.x==null || (e.acceleration.x==0&&e.acceleration.y==0&&e.acceleration.z==0)) callback(false);
89693
- else callback(true);
90029
+ // if (!e.acceleration || e.acceleration.x==null || (e.acceleration.x==0&&e.acceleration.y==0&&e.acceleration.z==0)) callback(false);
90030
+ if (!e.acceleration || e.acceleration.x==null) callback(false);
90031
+ else setEvents();
89694
90032
  }
89695
90033
  called = true;
89696
- WW.removeEventListener(permissionType, testMe);
89697
- }
90034
+ WW.removeEventListener(permissionType, testMe);
90035
+ }
89698
90036
  setTimeout(function(){
89699
90037
  if (!called) callback(false);
89700
90038
  }, 100);
89701
90039
  }
90040
+
90041
+ function setEvents() {
90042
+ callback(true);
90043
+ }
90044
+
90045
+ function setPane() {
90046
+ frame.canvas.style.pointerEvents = "none";
90047
+ that.show();
90048
+ document.addEventListener("mousedown", kmd);
90049
+ }
90050
+
90051
+ function kmd (e) {
90052
+ frame.canvas.style.pointerEvents = "auto";
90053
+ document.removeEventListener("mousedown", kmd);
90054
+ that.hide(true);
90055
+ if (e.clientY-frame.y <= that.y*frame.scale/2) { // yes
90056
+ if (pt == "mic" || pt == "cam" || pt == "miccam") {
90057
+ if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
90058
+ navigator.mediaDevices.getUserMedia({audio: (pt=="mic" || pt=="miccam"), video:(pt=="cam" || pt=="miccam") })
90059
+ .then(function(stream) {
90060
+ callback(stream);
90061
+ })
90062
+ .catch(function(err) {
90063
+ callback(false);
90064
+ });
90065
+ } else callback(false);
90066
+ } else {
90067
+ var s = DeviceMotionEvent;
90068
+ if (pt != "devicemotion") s = DeviceOrientationEvent;
90069
+ s.requestPermission().then(function(result) {
90070
+ if (result != "denied") {
90071
+ setEvents();
90072
+ okay = true;
90073
+ }
90074
+ else callback(false);
90075
+ }).catch(function(e){
90076
+ callback(false);
90077
+ });
90078
+ }
90079
+ } else {
90080
+ callback(false);
90081
+ }
90082
+ }
90083
+
89702
90084
  }
89703
90085
  zim.extend(zim.PermissionAsk, zim.Pane, null, "zimPane", false);//-83.01
89704
90086
 
@@ -94788,6 +95170,10 @@ keyOut(color, tolerance, replacement) - remove color from Cam's bitmap and a tol
94788
95170
  replacement (default clear) a color to replace the keyed out color with or an optional array to match the colors array if an array is used
94789
95171
  setFacingMode(mode) - set to "user", "exact_user", "environment", "exact_environment", "auto" to choose camera on mobile
94790
95172
  see facingMode parameter for more info
95173
+ getCanvas() - caches the cam display and adds updateCache to a cam.canvasTicker
95174
+ use this if a canvas showing what the cam sees is needed
95175
+ for instance with computer vision libraries like ML5 or TenserFlow, etc.
95176
+ forgetCanvas() - turn off getCanvas() cam display cache and Ticker function
94791
95177
  dispose() - close the cam and remove events
94792
95178
 
94793
95179
  ALSO: ZIM 4TH adds all the methods listed under Container (see above), such as: