— –  Created by: Takaaki Naganoya –  Created on: 2020/06/13 –  Modified on: 2023/03/07 — –  Copyright © 2020-2023 Piyomaru Software, All Rights Reserved — use AppleScript version "2.7" use framework "Foundation" use framework "AppKit" use framework "WebKit" use scripting additions
property |NSURL| : a reference to current application’s |NSURL| property NSAlert : a reference to current application’s NSAlert property NSString : a reference to current application’s NSString property NSButton : a reference to current application’s NSButton property WKWebView : a reference to current application’s WKWebView property WKUserScript : a reference to current application’s WKUserScript property NSURLRequest : a reference to current application’s NSURLRequest property NSRunningApplication : a reference to current application’s NSRunningApplication property NSUTF8StringEncoding : a reference to current application’s NSUTF8StringEncoding property WKUserContentController : a reference to current application’s WKUserContentController property WKWebViewConfiguration : a reference to current application’s WKWebViewConfiguration property WKUserScriptInjectionTimeAtDocumentEnd : a reference to current application’s WKUserScriptInjectionTimeAtDocumentEnd
property returnCode : 0
–https://www.cresco.co.jp/blog/entry/7427/ — By sgi-chang @ UX Design Center set myStr to "<!DOCTYPE html> <html>
<head>
      <title>three.js css3d – cresco xmas inspired by periodic table</title>     <meta charset=\"utf-8\">     <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0\">     <link type=\"text/css\" rel=\"stylesheet\" href=\"https://threejs.org/examples/main.css\">     <style>         a {             color: #8ff;         }
          #menu {             position: absolute;             bottom: 20px;             width: 100%;             text-align: center;         }
          .element {             width: 120px;             height: 160px;             box-shadow: 0px 0px 12px rgba(0, 255, 255, 0.5);             border: 1px solid rgba(127, 255, 255, 0.25);             font-family: Helvetica, sans-serif;             text-align: center;             line-height: normal;             cursor: default;         }
          .element:hover {             box-shadow: 0px 0px 12px rgba(0, 255, 255, 0.75);             border: 1px solid rgba(127, 255, 255, 0.75);         }
          .element .number {             position: absolute;             top: 20px;             right: 20px;             font-size: 12px;             color: rgba(127, 255, 255, 0.75);         }
          .element .symbol {             position: absolute;             top: 40px;             left: 0px;             right: 0px;             font-size: 60px;             font-weight: bold;             color: rgba(255, 255, 255, 0.75);             text-shadow: 0 0 10px rgba(0, 255, 255, 0.95);         }
          .element .details {             position: absolute;             bottom: 15px;             left: 0px;             right: 0px;             font-size: 12px;             color: rgba(127, 255, 255, 0.75);         }
          button {             color: rgba(127, 255, 255, 0.75);             background: transparent;             outline: 1px solid rgba(127, 255, 255, 0.75);             border: 0px;             padding: 5px 10px;             cursor: pointer;         }
          button:hover {             background-color: rgba(0, 255, 255, 0.5);         }
          button:active {             color: #000000;             background-color: rgba(0, 255, 255, 0.75);         }     </style> </head>
<body>
      <script src=\"https://threejs.org/examples/jsm/libs/tween.module.min.js\"></script>     <script src=\"https://threejs.org/examples/jsm/controls/TrackballControls.js\"></script>     <script src=\"https://threejs.org/examples/jsm/renderers/CSS3DRenderer.js\"></script>
      <div id=\"info\"><a href=\"http://piyocast.com/as\" target=\"_blank\">AppleScript 3D UI Demonstration</a> By Piyomaru Software</div>     <div id=\"container\"></div>     <div id=\"menu\">         <button id=\"table\">TABLE</button>         <button id=\"sphere\">SPHERE</button>         <button id=\"helix\">HELIX</button>         <button id=\"grid\">GRID</button>     </div>
      <!– Import maps polyfill –>     <!– Remove this when import maps will be widely supported –>     <script async src=\"https://unpkg.com/es-module-shims@1.5.8/dist/es-module-shims.js\"></script>
      <script type=\"importmap\">       {         \"imports\": {           \"three\": \"https://unpkg.com/three@0.142.0/build/three.module.js\",           \"OrbitControls\": \"https://unpkg.com/three@0.142.0/examples/jsm/controls/OrbitControls.js\"         }       }     </script>          <script type=\"module\">         import * as THREE from ’https://threejs.org/build/three.module.js’;         import { TWEEN } from ’https://threejs.org/examples/jsm/libs/tween.module.min.js’;         import { TrackballControls } from ’https://threejs.org/examples/jsm/controls/TrackballControls.js’;         import { CSS3DRenderer, CSS3DObject } from ’https://threejs.org/examples/jsm/renderers/CSS3DRenderer.js’;              var table = [             \"1\", \"Hydrogen\", \"1.00794\", 1, 1,             \"2\", \"Helium\", \"4.002602\", 1, 2,             \"3\", \"Lithium\", \"6.941\", 1, 3,             \"4\", \"Beryllium\", \"9.012182\", 1, 4,             \"5\", \"Boron\", \"10.811\", 1, 5,             \"6\", \"Carbon\", \"12.0107\", 2, 1,             \"7\", \"Nitrogen\", \"14.0067\", 2, 3,             \"8\", \"Oxygen\", \"15.9994\", 3, 1,             \"9\", \"Fluorine\", \"18.9984032\", 3, 3,             \"101\", \"Saturday\", \"July\", 4, 2,             \"I\", \"Moscovium\", \"(290)\", 6, 1,             \"I\", \"Livermorium\", \"(293)\", 6, 2,             \"I\", \"Tennessine\", \"(294)\", 6, 3,             \"I\", \"Titanium\", \"47.867\", 6, 4,             \"I\", \"Vanadium\", \"50.9415\", 6, 5,             \"Y\", \"Chromium\", \"51.9961\", 8, 1,             \"Y\", \"Manganese\", \"54.938045\", 9, 2,             \"Y\", \"Iron\", \"55.845\", 10, 3,             \"Y\", \"Cobalt\", \"58.933195\", 10, 4,             \"Y\", \"Nickel\", \"58.6934\", 10, 5,             \"Y\", \"Copper\", \"63.546\", 11, 2,             \"Y\", \"Zinc\", \"65.38\", 12, 1,             \"O\", \"Gallium\", \"69.723\", 14, 1,             \"O\", \"Copernicium\", \"(285)\", 14, 2,             \"O\", \"Nihonium\", \"(286)\", 14, 3,             \"O\", \"Oganesson\", \"(294)\", 14, 4,             \"O\", \"Neon\", \"20.1797\", 14, 5,             \"O\", \"Sodium\", \"22.98976…\", 15, 1,             \"O\", \"Magnesium\", \"24.305\", 15, 5,             \"O\", \"Aluminium\", \"26.9815386\", 16, 1,             \"O\", \"Silicon\", \"28.0855\", 16, 5,             \"O\", \"Phosphorus\", \"30.973762\", 17, 1,             \"O\", \"Sulfur\", \"32.065\", 17, 2,             \"O\", \"Chlorine\", \"35.453\", 17, 3,             \"O\", \"Argon\", \"39.948\", 17, 4,             \"O\", \"Potassium\", \"39.948\", 17, 5,             \"M\", \"Calcium\", \"40.078\", 1, 7,             \"M\", \"Scandium\", \"44.955912\", 1, 8,             \"M\", \"Roentgenium\", \"(280)\", 1, 9,             \"M\", \"Germanium\", \"72.63\", 1, 10,             \"M\", \"Lead\", \"207.2\", 1, 11,                   \"M\", \"Arsenic\", \"74.9216\", 2, 8,             \"M\", \"Selenium\", \"78.96\", 3, 9,             \"M\", \"Bromine\", \"79.904\", 3, 10,             \"M\", \"Krypton\", \"83.798\", 4, 8,             \"M\", \"Rubidium\", \"85.4678\", 5, 7,             \"M\", \"Strontium\", \"87.62\", 5, 8,             \"M\", \"Yttrium\", \"88.90585\", 5, 9,             \"M\", \"Zirconium\", \"91.224\", 5, 10,             \"M\", \"Niobium\", \"92.90628\", 5, 11,             \"A\", \"Molybdenum\", \"95.96\", 7,8,             \"A\", \"Technetium\", \"(98)\", 7, 9,             \"A\", \"Ruthenium\", \"101.07\", 7, 10,             \"A\", \"Rhodium\", \"102.9055\",7, 11,             \"A\", \"Palladium\", \"106.42\", 8, 7,             \"A\", \"Silver\", \"107.8682\", 8,9,             \"A\", \"Cadmium\", \"112.411\", 9, 7,             \"A\", \"Indium\", \"114.818\", 9, 9,             \"A\", \"Tin\", \"118.71\", 10, 8,             \"A\", \"Antimony\", \"121.76\", 10, 9,             \"A\", \"Gadolinium\", \"157.25\", 10, 10,             \"A\", \"Terbium\", \"158.92535\", 10, 11,             \"R\", \"Dysprosium\", \"162.5\", 12, 7,             \"R\", \"Holmium\", \"164.93032\", 12, 8,             \"R\", \"Erbium\", \"167.259\", 12, 9,             \"R\", \"Thulium\", \"168.93421\", 12, 10,             \"R\", \"Ytterbium\", \"173.054\", 12, 11,             \"R\", \"Lutetium\", \"174.9668\", 13, 7,             \"R\", \"Hafnium\", \"178.49\", 13, 9,             \"R\", \"Samarium\", \"150.36\", 14, 7,             \"R\", \"Europium\", \"151.964\", 14, 9,             \"R\", \"Tantalum\", \"180.94788\", 15, 8,             \"R\", \"Tungsten\", \"183.84\", 15, 10,             \"R\", \"Rhenium\", \"186.207\", 15, 11,             \"U\", \"Osmium\", \"190.23\", 17, 7,             \"U\", \"Iridium\", \"192.217\", 17,8,             \"U\", \"Platinum\", \"195.084\", 17, 9,             \"U\", \"Gold\", \"196.966569\", 17, 10,             \"U\", \"Mercury\", \"200.59\", 18, 11,             \"U\", \"Thallium\", \"204.3833\", 19, 11,             \"U\", \"Bismuth\", \"208.9804\", 20, 7,             \"U\", \"Polonium\", \"(209)\", 20, 8,             \"U\", \"Astatine\", \"(210)\", 20, 9,             \"U\", \"Francium\", \"(223)\", 20, 10,             \"U\", \"Radium\", \"(226)\", 22, 9,             \"U\", \"Actinium\", \"(227)\", 22, 10,             \"U\", \"Thorium\", \"232.03806\", 22, 11,             \"A\", \"Protactinium\", \"231.0588\", 22, 7,             \"A\", \"Uranium\", \"238.02891\", 23, 9,             \"A\", \"Neptunium\", \"(237)\", 23, 8,             \"A\", \"Plutonium\", \"(244)\", 23, 9,             \"A\", \"Americium\", \"(243)\", 23, 10,             \"A\", \"Curium\", \"(247)\", 23, 11,             \"S\", \"Berkelium\", \"(247)\", 24, 7,             \"S\", \"Californium\", \"(251)\", 24, 8,             \"S\", \"Einstenium\", \"(252)\", 24, 9,             \"S\", \"Fermium\", \"(257)\", 24, 11,             \"S\", \"Mendelevium\", \"(258)\", 25, 7,             \"S\", \"Nobelium\", \"(259)\", 25, 9,             \"S\", \"Lawrencium\", \"(262)\", 25, 11,             \"S\", \"Rutherfordium\", \"(267)\", 26, 7,             \"S\", \"Dubnium\", \"(268)\", 26, 9,             \"S\", \"Seaborgium\", \"(271)\", 26, 10,             \"S\", \"Bohrium\", \"(272)\", 26, 11,             \"A\", \"Hassium\", \"(270)\", 27, 8,             \"B\", \"Meitnerium\", \"(276)\", 27, 9,             \"C\", \"Darmstadium\", \"(281)\", 27, 8,             \"D\", \"Tellurium\", \"127.6\", 27, 9,             \"E\", \"Iodine\", \"126.90447\", 27, 10,             \"F\", \"Xenon\", \"131.293\", 28, 9,             \"G\", \"Caesium\", \"132.9054\", 28, 10,             \"H\", \"Barium\", \"132.9054\", 28, 11,             \"I\", \"Lanthanum\", \"138.90547\", 29, 8,             \"J\", \"Cerium\", \"140.116\", 29, 9,             \"K\", \"Praseodymium\", \"140.90765\", 29, 10,             \"L\", \"Neodymium\", \"144.242\", 29, 8,             \"M\", \"Promethium\", \"(145)\", 29, 9,   \"PS\", \"Piyomaru Software\", \"(PiyoPiyo)\", 29, 10,     \"AS\", \"AppleScript\", \"(osalang)\", 29, 11,           ];           var camera, scene, renderer;         var controls;         var objects = [];         var targets = { table: [], sphere: [], helix: [], grid: [] };         init();         animate();              function init() {             camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 10000);             camera.position.z = 3000;             scene = new THREE.Scene();                    // table             for (var i = 0; i < table.length; i += 5) {                        var element = document.createElement(’div’);                 element.className = ’element’;
       //element.style.backgroundColor = ’rgba(128,0,64,’ + ( Math.random() * 0.5 + 0.25 ) + ’)’;     //element.style.backgroundColor = ’rgba(64,0,128,’ + ( Math.random() * 0.5 + 0.25 ) + ’)’;                //element.style.backgroundColor = ’rgba(0,0,0,’ + ( Math.random() * 0.5 + 0.25 ) + ’)’;                element.style.backgroundColor = ’rgba(0,127,127,’ + ( Math.random() * 0.5 + 0.25 ) + ’)’;                 //element.style.backgroundColor = ’rgba(18,77,174,’ + (Math.random() * 0.5 + 0.25) + ’)’;
                  var number = document.createElement(’div’);                 number.className = ’number’;                 number.textContent = (i / 5) + 1;                 element.appendChild(number);                 var symbol = document.createElement(’div’);                 symbol.className = ’symbol’;                 symbol.textContent = table[i];                 element.appendChild(symbol);                 var details = document.createElement(’div’);                 details.className = ’details’;                 details.innerHTML = table[i + 1] + ’<br>’ + table[i + 2];                 element.appendChild(details);                 var object = new CSS3DObject(element);                 object.position.x = Math.random() * 4000 – 2000;                 object.position.y = Math.random() * 4000 – 2000;                 object.position.z = Math.random() * 4000 – 2000;                 scene.add(object);                 objects.push(object);                 //                 var object = new THREE.Object3D();                 object.position.x = (table[i + 3] * 140) – 1330;                 object.position.y = – (table[i + 4] * 180) + 990;                 targets.table.push(object);             }                    // sphere             var vector = new THREE.Vector3();             for (var i = 0, l = objects.length; i < l; i++) {                 var phi = Math.acos(- 1 + (2 * i) / l);                 var theta = Math.sqrt(l * Math.PI) * phi;                 var object = new THREE.Object3D();                 object.position.setFromSphericalCoords(800, phi, theta);                 vector.copy(object.position).multiplyScalar(2);                 object.lookAt(vector);                 targets.sphere.push(object);             }                    // helix             var vector = new THREE.Vector3();             for (var i = 0, l = objects.length; i < l; i++) {                 var theta = i * 0.175 + Math.PI;                 var y = – (i * 8) + 450;                 var object = new THREE.Object3D();                 object.position.setFromCylindricalCoords(900, theta, y);                 vector.x = object.position.x * 2;                 vector.y = object.position.y;                 vector.z = object.position.z * 2;                 object.lookAt(vector);                 targets.helix.push(object);             }                    // grid             for (var i = 0; i < objects.length; i++) {                 var object = new THREE.Object3D();                 object.position.x = ((i % 5) * 400) – 800;                 object.position.y = (- (Math.floor(i / 5) % 5) * 400) + 800;                 object.position.z = (Math.floor(i / 25)) * 1000 – 2000;                 targets.grid.push(object);             }                    //             renderer = new CSS3DRenderer();             renderer.setSize(window.innerWidth, window.innerHeight);             document.getElementById(’container’).appendChild(renderer.domElement);                    //             controls = new TrackballControls(camera, renderer.domElement);             controls.minDistance = 500;             controls.maxDistance = 6000;             controls.addEventListener(’change’, render);                    var button = document.getElementById(’table’);             button.addEventListener(’click’, function () {                 transform(targets.table, 2000);             }, false);                    var button = document.getElementById(’sphere’);             button.addEventListener(’click’, function () {                 transform(targets.sphere, 2000);             }, false);                    var button = document.getElementById(’helix’);             button.addEventListener(’click’, function () {                 transform(targets.helix, 2000);             }, false);                    var button = document.getElementById(’grid’);             button.addEventListener(’click’, function () {                 transform(targets.grid, 2000);             }, false);                    transform(targets.table, 2000);             //             window.addEventListener(’resize’, onWindowResize, false);         }              function transform(targets, duration) {             TWEEN.removeAll();             for (var i = 0; i < objects.length; i++) {                 var object = objects[i];                 var target = targets[i];                 new TWEEN.Tween(object.position)                     .to({ x: target.position.x, y: target.position.y, z: target.position.z }, Math.random() * duration + duration)                     .easing(TWEEN.Easing.Exponential.InOut)                     .start();                 new TWEEN.Tween(object.rotation)                     .to({ x: target.rotation.x, y: target.rotation.y, z: target.rotation.z }, Math.random() * duration + duration)                     .easing(TWEEN.Easing.Exponential.InOut)                     .start();             }             new TWEEN.Tween(this)                 .to({}, duration * 2)                 .onUpdate(render)                 .start();         }              function onWindowResize() {             camera.aspect = window.innerWidth / window.innerHeight;             camera.updateProjectionMatrix();             renderer.setSize(window.innerWidth, window.innerHeight);             render();         }              function animate() {             requestAnimationFrame(animate);             TWEEN.update();             controls.update();         }              function render() {             renderer.render(scene, camera);         }     </script> </body>
</html>" 
set paramObj to {myMessage:"WebGL & three.js Test", mySubMessage:"This is a WebGL UI using three.js", htmlStr:myStr} –my browseStrWebContents:paramObj–for debug my performSelectorOnMainThread:"browseStrWebContents:" withObject:(paramObj) waitUntilDone:true
on browseStrWebContents:paramObj   set aMainMes to myMessage of paramObj   set aSubMes to mySubMessage of paramObj   set htmlString to (htmlStr of paramObj)      set aWidth to 1600   set aHeight to 900      –WebViewをつくる   set aConf to WKWebViewConfiguration’s alloc()’s init()      –指定HTML内のJavaScriptをFetch   set jsSource to pickUpFromToStr(htmlString, "<script src", "</script>") of me      set userScript to WKUserScript’s alloc()’s initWithSource:jsSource injectionTime:(WKUserScriptInjectionTimeAtDocumentEnd) forMainFrameOnly:true   set userContentController to WKUserContentController’s alloc()’s init()   userContentController’s addUserScript:(userScript)   aConf’s setUserContentController:userContentController      set aWebView to WKWebView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight)) configuration:aConf   aWebView’s setNavigationDelegate:me   aWebView’s setUIDelegate:me   aWebView’s setTranslatesAutoresizingMaskIntoConstraints:true   using terms from scripting additions     set bURL to |NSURL|’s fileURLWithPath:(POSIX path of (path to me))   end using terms from   aWebView’s loadHTMLString:htmlString baseURL:(bURL)      — set up alert     set theAlert to NSAlert’s alloc()’s init()   tell theAlert     its setMessageText:aMainMes     its setInformativeText:aSubMes     its addButtonWithTitle:"OK"     –its addButtonWithTitle:"Cancel"     its setAccessoryView:aWebView          set myWindow to its |window|   end tell      — show alert in modal loop   NSRunningApplication’s currentApplication()’s activateWithOptions:0   my performSelectorOnMainThread:"doModal:" withObject:(theAlert) waitUntilDone:true      –Stop Web View Action   set bURL to |NSURL|’s URLWithString:"about:blank"   set bReq to NSURLRequest’s requestWithURL:bURL   aWebView’s loadRequest:bReq      if (my returnCode as number) = 1001 then error number -128 end browseStrWebContents:
on doModal:aParam   set (my returnCode) to (aParam’s runModal()) as number end doModal:
on viewDidLoad:aNotification   return true end viewDidLoad:
on fetchJSSourceString(aURL)   set jsURL to |NSURL|’s URLWithString:aURL   set jsSourceString to NSString’s stringWithContentsOfURL:jsURL encoding:(NSUTF8StringEncoding) |error|:(missing value)   return jsSourceString end fetchJSSourceString
on pickUpFromToStr(aStr as string, s1Str as string, s2Str as string)   set a1Offset to offset of s1Str in aStr   if a1Offset = 0 then return false   set bStr to text (a1Offset + (length of s1Str)) thru -1 of aStr   set a2Offset to offset of s2Str in bStr   if a2Offset = 0 then return false   set cStr to text 1 thru (a2Offset – (length of s2Str)) of bStr   return cStr as string end pickUpFromToStr
–リストを任意のデリミタ付きでテキストに on retArrowText(aList, aDelim)   set aText to ""   set curDelim to AppleScript’s text item delimiters   set AppleScript’s text item delimiters to aDelim   set aText to aList as text   set AppleScript’s text item delimiters to curDelim   return aText end retArrowText
on array2DToJSONArray(aList)   set anArray to current application’s NSMutableArray’s arrayWithArray:aList   set jsonData to current application’s NSJSONSerialization’s dataWithJSONObject:anArray options:(0 as integer) |error|:(missing value) –0 is    set resString to current application’s NSString’s alloc()’s initWithData:jsonData encoding:(current application’s NSUTF8StringEncoding)   return resString end array2DToJSONArray
on parseByDelim(aData, aDelim)   set curDelim to AppleScript’s text item delimiters   set AppleScript’s text item delimiters to aDelim   set dList to text items of aData   set AppleScript’s text item delimiters to curDelim   return dList end parseByDelim
 |