diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..6948976 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 oligami + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 4824b5f..7b47c8d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # IroSphere これは[Tali](https://github.com/TaliPhoto)さんが、[youtube](https://youtu.be/jrCr4j_qdPo)で紹介した、アイデアまで含めてCC0のソフトであるIroSphereというソフトをtauriというフレームワークで一から書き直したものです。
-[本家](https://github.com/TaliPhoto/IroSphere) +[本家](https://github.com/TaliPhoto/IroSphere)
機能の要望などはissueなどにお願いします。 ## install方法 @@ -12,7 +12,8 @@ linux(debian系列): deb
linux: AppImage
mac: dmg
※私はwindowユーザーなので、web版以外は実際に他のOSで正常に動作するかは知りません
-※linuxではrustがlowercaseな都合上アプリ名がiro-sphereとなっているようなので気を付けてください +※linuxではrustがlowercaseな都合上アプリ名がiro-sphereとなっているようなので気を付けてください
+実際のサイズは6.6MB程です! 手軽にどうぞ! (Windows) ## 使い方 画像をクリックまたは長押しで右のSphereに色が付きます。
@@ -33,6 +34,7 @@ Fキーなどの便利機能や他の機能などは搭載していません。 - fキーの実装 - リセット方法がない - スマホ用に縦長モードを搭載 +- ショトカ以外でファイルを開く方法を考える ## License Mit Licenseです。アイコンなどがデフォルトのままですから... diff --git a/index.html b/index.html index ec38b28..104a344 100644 --- a/index.html +++ b/index.html @@ -5,6 +5,7 @@ IroSphere + diff --git a/package-lock.json b/package-lock.json index b7bb6e2..5013e3f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,18 @@ { "name": "irosphere", - "version": "1.0.2", + "version": "1.0.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "irosphere", - "version": "1.0.2", + "version": "1.0.3", "dependencies": { "@tauri-apps/api": "^1.2.0" }, "devDependencies": { "@types/three": "^0.150.1", + "sass": "^1.61.0", "three": "^0.151.2", "typescript": "^4.9.3", "vite": "^4.2.0" @@ -407,6 +408,67 @@ "integrity": "sha512-xlFXPfgJR5vIuDefhaHuUM9uUgvPaXB6GKdXy2gdEh8gBWQZ2ul24AJz3foUd8NNKlSTQuWYJpCb1/pL81m1KQ==", "dev": true }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, "node_modules/esbuild": { "version": "0.17.15", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.15.tgz", @@ -450,6 +512,18 @@ "integrity": "sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==", "dev": true }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", @@ -470,6 +544,18 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -482,6 +568,24 @@ "node": ">= 0.4.0" } }, + "node_modules/immutable": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz", + "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-core-module": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", @@ -494,6 +598,36 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/lil-gui": { "version": "0.17.0", "resolved": "https://registry.npmjs.org/lil-gui/-/lil-gui-0.17.0.tgz", @@ -518,6 +652,15 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -530,6 +673,18 @@ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "dev": true }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/postcss": { "version": "8.4.21", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", @@ -554,6 +709,18 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -587,6 +754,23 @@ "fsevents": "~2.3.2" } }, + "node_modules/sass": { + "version": "1.61.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.61.0.tgz", + "integrity": "sha512-PDsN7BrVkNZK2+dj/dpKQAWZavbAQ87IXqVvw2+oEYI+GwlTWkvbQtL7F2cCNbMqJEYKPh1EcjSxsnqIb/kyaQ==", + "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", @@ -614,6 +798,18 @@ "integrity": "sha512-tGaLRP2H6++tj2JumHD25slhFAx0C619rl6G6Utjq7JTrDGJwDxpu+J2XpnYIUMfEmhNvIFDQJfp79JtKmNBWw==", "dev": true }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/typescript": { "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", diff --git a/package.json b/package.json index 77ac136..70cf7e8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "irosphere", "private": true, - "version": "1.0.2", + "version": "1.0.3", "type": "module", "scripts": { "tauri": "tauri", @@ -12,6 +12,7 @@ }, "devDependencies": { "@types/three": "^0.150.1", + "sass": "^1.61.0", "three": "^0.151.2", "typescript": "^4.9.3", "vite": "^4.2.0" diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 7206d4a..4075b8d 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -4,7 +4,7 @@ version = 3 [[package]] name = "IroSphere" -version = "1.0.2" +version = "1.0.3" dependencies = [ "hotwatch", "serde", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 349dc8d..f9fa717 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "IroSphere" -version = "1.0.2" +version = "1.0.3" description = "A Tauri App" authors = ["oligami"] license = "MIT License" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index c1708d4..dcf364d 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -7,7 +7,7 @@ }, "package": { "productName": "IroSphere", - "version": "1.0.2" + "version": "1.0.3" }, "tauri": { "allowlist": { diff --git a/src/3dviewer.ts b/src/3dviewer.ts index 2b651e6..e760cc1 100644 --- a/src/3dviewer.ts +++ b/src/3dviewer.ts @@ -5,7 +5,7 @@ import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; // https://white-sesame.jp/archives/blog/3062 export function threeviewer(threecanvas: any, param: { initNodeNumS: number, initNodeNumL: number, initNodeNumH: number }) { - let unlisten_resize: any; + // let unlisten_resize: any; const scene = new THREE.Scene(); scene.background = new THREE.Color(0xd0d0d0); @@ -17,7 +17,7 @@ export function threeviewer(threecanvas: any, param: { initNodeNumS: number, ini camera.lookAt(0, 0, 0); // 注視点の座標 const controls = new OrbitControls(camera, threecanvas) controls.enableDamping = true; - controls.dampingFactor = 0.2;; + controls.dampingFactor = 0.2; let renderer: any if (threecanvas) @@ -31,11 +31,15 @@ export function threeviewer(threecanvas: any, param: { initNodeNumS: number, ini const group = new THREE.Group(); - var additiveNodesNum = 0 var additiveNodesBeforePos: { x: number, y: number } - let additiveNodes: THREE.Mesh[] = [] - const AdditiveNodesGroup = new THREE.Group(); - group.add(AdditiveNodesGroup) + let additiveNodes: { opecode: string, data: any }[] = [] + let beforeAdditiveNodes: { opecode: string, data: any }[] = [] + var continuityKeyAction_Ctrl_z: boolean = true; + var continuityKeyAction_Ctrl_z_is_start: boolean = true; + var continuityKeyAction_Ctrl_y: boolean = true; + var continuityKeyAction_Ctrl_y_is_start: boolean = true; + const additiveNodesGroup = new THREE.Group(); + group.add(additiveNodesGroup) var group_sphere: any = []; scene.add(group) @@ -77,6 +81,105 @@ export function threeviewer(threecanvas: any, param: { initNodeNumS: number, ini group.add(mesh) } + const allAddictiveNodeDelete = () => { + const additiveNodesAll = additiveNodes.filter(v => (v.opecode == 'add_one')).map(v => { + additiveNodesGroup.remove(v.data) + return v.data + }) + additiveNodes.push({ opecode: 'remove_all', data: additiveNodesAll }) + beforeAdditiveNodes.length = 0 + } + + const allAddictiveNodeDeleteImgChange = () => { + const additiveNodesAll = additiveNodes.filter(v => (v.opecode == 'add_one')).map(v => { + additiveNodesGroup.remove(v.data) + return v.data + }) + additiveNodes.push({ opecode: 'remove_all_img_change', data: additiveNodesAll }) + beforeAdditiveNodes.length = 0 + } + + document.addEventListener('keyup', event => { + if (event.altKey || event.ctrlKey) { + if (event.key == 'r' || event.key == 'd') { + allAddictiveNodeDelete() + } + if (event.key == 'z') { + continuityKeyAction_Ctrl_z = true + continuityKeyAction_Ctrl_z_is_start = true + } + if (event.key == 'y') { + continuityKeyAction_Ctrl_y = true + continuityKeyAction_Ctrl_y_is_start = true + } + } + }) + document.addEventListener('keydown', event => { + if (event.altKey || event.ctrlKey) { + if (event.key == 'z') { + if (continuityKeyAction_Ctrl_z) { + const lastAdditiveNodes = additiveNodes.pop() + var cancel_node: boolean = false + if (lastAdditiveNodes) { + if (lastAdditiveNodes.opecode == 'add_one') + additiveNodesGroup.remove(lastAdditiveNodes.data) + if (lastAdditiveNodes.opecode == 'remove_all') + lastAdditiveNodes.data.forEach((v: any) => { + additiveNodesGroup.add(v) + }) + if (lastAdditiveNodes.opecode == 'remove_all_img_change') { + if (continuityKeyAction_Ctrl_z_is_start) + lastAdditiveNodes.data.forEach((v: any) => { + additiveNodesGroup.add(v) + }) + else { + continuityKeyAction_Ctrl_z = false + cancel_node = true + } + } + if (cancel_node) + additiveNodes.push(lastAdditiveNodes) + else { + beforeAdditiveNodes.push(lastAdditiveNodes) + continuityKeyAction_Ctrl_z_is_start = false; + } + } + } + } + if (event.key == 'y') { + if (continuityKeyAction_Ctrl_y) { + const lastAdditiveNodes = beforeAdditiveNodes.pop() + var cancel_node: boolean = false + if (lastAdditiveNodes) { + if (lastAdditiveNodes.opecode == 'add_one') { + additiveNodesGroup.add(lastAdditiveNodes.data) + } + if (lastAdditiveNodes.opecode == 'remove_all') + lastAdditiveNodes.data.forEach((v: any) => { + additiveNodesGroup.remove(v) + }); + if (lastAdditiveNodes.opecode == 'remove_all_img_change') { + if (continuityKeyAction_Ctrl_y_is_start) + lastAdditiveNodes.data.forEach((v: any) => { + additiveNodesGroup.remove(v) + }); + else { + continuityKeyAction_Ctrl_y = false + cancel_node = true + } + } + if (cancel_node) + beforeAdditiveNodes.push(lastAdditiveNodes) + else { + additiveNodes.push(lastAdditiveNodes) + continuityKeyAction_Ctrl_y_is_start = false; + } + } + } + } + } + }, false); // 第一引数にkeyupを記述 + for (var k = 0; k < param.initNodeNumL; ++k) { const elevation = param.initNodeNumL == 1 ? 0.0 : Math.PI * 2 / param.initNodeNumL * k; for (var j = 1; j <= param.initNodeNumS; ++j) { @@ -90,7 +193,6 @@ export function threeviewer(threecanvas: any, param: { initNodeNumS: number, ini } } - const colorSphereMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff, transparent: true, opacity: 0.5 }); const colorSphereGeometry = new THREE.SphereGeometry(0.1); // サイズ, 分割数 const colorSphereMesh = new THREE.Mesh(colorSphereGeometry, colorSphereMaterial); @@ -101,7 +203,7 @@ export function threeviewer(threecanvas: any, param: { initNodeNumS: number, ini group.rotation.x += 0.4; group.rotation.y += 0.4; - unlisten_resize = await window.addEventListener('resize', () => { + /* unlisten_resize = */await window.addEventListener('resize', () => { renderer.setSize(window.innerWidth / 2, window.innerHeight) const aspect_camera = aspectCamera([window.innerWidth / 2, window.innerHeight]); camera.left = -aspect_camera[0] @@ -130,10 +232,10 @@ export function threeviewer(threecanvas: any, param: { initNodeNumS: number, ini const colorSphereMesh = new THREE.Mesh(colorSphereGeometry, colorSphereMaterial); colorSphereMesh.position.set(pos.x, pos.y, pos.z) - additiveNodes.push(colorSphereMesh) - AdditiveNodesGroup.add(additiveNodes[additiveNodesNum]) + additiveNodes.push({ opecode: 'add_one', data: colorSphereMesh }) + beforeAdditiveNodes.length = 0 + additiveNodesGroup.add(colorSphereMesh) additiveNodesBeforePos = { x: image_position[0], y: image_position[1] } - ++additiveNodesNum } window.addEventListener("mousemove", e => { @@ -185,14 +287,16 @@ export function threeviewer(threecanvas: any, param: { initNodeNumS: number, ini let key_down: { w: boolean, a: boolean, s: boolean, d: boolean }; key_down = { w: false, a: false, s: false, d: false } const key_func = function (event: KeyboardEvent, press: boolean) { - if (event.key == "w") - key_down.w = press - if (event.key == "a") - key_down.a = press - if (event.key == "s") - key_down.s = press - if (event.key == "d") - key_down.d = press + if (!event.ctrlKey && !event.altKey) { + if (event.key == "w") + key_down.w = press + if (event.key == "a") + key_down.a = press + if (event.key == "s") + key_down.s = press + if (event.key == "d") + key_down.d = press + } } document.addEventListener('keydown', e => key_func(e, true), false); // 第一引数にkeydownを記述 document.addEventListener('keyup', e => key_func(e, false), false); // 第一引数にkeyupを記述 @@ -220,10 +324,11 @@ export function threeviewer(threecanvas: any, param: { initNodeNumS: number, ini animate(); })() - return () => { - if (unlisten_resize) - unlisten_resize(); - } + // return () => { + // if (unlisten_resize) + // unlisten_resize(); + // } + return allAddictiveNodeDeleteImgChange; } function aspectCamera(size: [number, number]): [number, number] { diff --git a/src/img.ts b/src/img.ts index b4bb14e..86ecd13 100644 --- a/src/img.ts +++ b/src/img.ts @@ -8,7 +8,7 @@ import { randInt } from 'three/src/math/MathUtils' import { listen_img_load, onFileDropEvent, open_file_dialog } from './tauri_or_web' // https://zenn.dev/kumassy/books/6e518fe09a86b2/viewer/1dbeeb\ -export function img_load_init() { +export function img_load_init(reset_img_callback: any) { let img_src_size: [number, number] let unlisten_resize: any; @@ -24,22 +24,22 @@ export function img_load_init() { file_img!.crossOrigin = 'anonymous' if (file_img?.parentElement) { file_img.src = Array(ColorBarSample, FlowerSample, KawaiiSample, MountainSample, PenguinSample, WindmillSample)[randInt(0, 5)] - get_img_src_size(file_img.src, load_img) + get_img_src_size(file_img.src, load_img, reset_img_callback) } - onFileDropEvent(load_img) + onFileDropEvent(load_img, reset_img_callback) document.addEventListener('keyup', e => { - if (e.ctrlKey && e.key == 'o') { - open_file_dialog(load_img) - } - if (e.altKey && e.key == 'o') { - open_file_dialog(load_img) + if (e.ctrlKey || e.altKey) { + if (e.key == 'o') { + e.stopImmediatePropagation() + open_file_dialog(load_img) + } } }, false); (async () => { - listen_img_load(load_img) + listen_img_load(load_img, reset_img_callback) unlisten_resize = await window.addEventListener('resize', () => load_img(img_src_size)); })(); @@ -54,10 +54,11 @@ export function img_load(path: string) { file_img!.src = path } -export function get_img_src_size(src: string, callback: (result: [number, number]) => void) { +export function get_img_src_size(src: string, callback: (result: [number, number]) => void, reset_img_callback: any) { var img = new Image(); img.src = src img.onload = () => callback([img.width, img.height]) + reset_img_callback() } function img_size_aspect(src_size: [number, number], size: [number, number]): [number, number] { @@ -71,18 +72,18 @@ function img_size_aspect(src_size: [number, number], size: [number, number]): [n } } -export function open_file_dialog_web(load_img: any) { +export function open_file_dialog_web(load_img: any, reset_img_callback: any) { const input = document.createElement('input'); input.type = 'file'; input.accept = 'image/*'; input.onchange = event => { const file = (event!.target! as HTMLInputElement)!.files![0]; - read_file_and_load_img(file, load_img) + read_file_and_load_img(file, load_img, reset_img_callback) }; input.click(); } -export function read_file_and_load_img(file: File, load_img: any) { +export function read_file_and_load_img(file: File, load_img: any, reset_img_callback: any) { const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = (e) => { @@ -90,7 +91,7 @@ export function read_file_and_load_img(file: File, load_img: any) { if (typeof (filepath_impl) == 'string') { const filepath = filepath_impl img_load(filepath) - get_img_src_size(filepath, load_img) + get_img_src_size(filepath, load_img, reset_img_callback) } }; } \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index f299292..a461b17 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,5 +1,4 @@ // import { invoke } from '@tauri-apps/api' -import './style.css' import { threeviewer } from './3dviewer' import { img_load_init } from './img' import { registerShortcut } from './tauri_or_web'; @@ -16,6 +15,7 @@ document.querySelector('#app')!.innerHTML = ` window.addEventListener("DOMContentLoaded", () => { }); -img_load_init() +const reset_img_callback = threeviewer(document.getElementById("threeCanvas"), { initNodeNumS: 7, initNodeNumL: 28, initNodeNumH: 15 }) + +img_load_init(reset_img_callback) -threeviewer(document.getElementById("threeCanvas"), { initNodeNumS: 7, initNodeNumL: 28, initNodeNumH: 15 }) diff --git a/src/style.css b/src/style.css deleted file mode 100644 index 34f75dc..0000000 --- a/src/style.css +++ /dev/null @@ -1,82 +0,0 @@ -:root { - font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; - line-height: 1.5; - font-weight: 400; - - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - /* background-color: #242424; */ - background-color: #d0d0d0; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - - /* ビヨヨン効果を無効化する 及び スクロール削除 */ - overscroll-behavior: none; - overflow: clip; - overflow-wrap: unset; - overflow-inline: hidden; - padding-top: 0; -} - -#app { - margin: 0 auto; - padding: 0rem; - text-align: center; -} - -input, -button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - /* background-color: #1a1a1a; */ - background-color: #d0d0d0; - transition: border-color 0.25s; -} - -.flex { - display: flex; - padding: 0px; - max-width: 100%; -} - -#file_img_wrapper { - max-width: 100%; - max-height: 100%; - margin-top: auto; - margin-bottom: auto; - background-color: #d0d0d0; -} - -#file_img { - user-select: none; - /* user-drag: none; */ - -webkit-user-drag: none; - -moz-user-select: none; -} - -body { - margin: 0; - display: flex; - place-items: center; - background-color: #d0d0d0; -} - -@media (prefers-color-scheme: light) { - :root { - /* color: #213547; */ - color: #d0d0d0; - background-color: #ffffff; - } - - button { - background-color: #f9f9f9; - } -} \ No newline at end of file diff --git a/src/style.scss b/src/style.scss new file mode 100644 index 0000000..33781df --- /dev/null +++ b/src/style.scss @@ -0,0 +1,100 @@ +$background-color_dark: #d0d0d0; +$background-color_light: #d0d0d0; +$color: contrast-color($background-color_dark); +$font-family_default: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; +$font-family_btn: inherit; + +@page :root { + font-family: $font-family_default; + line-height: 1.5; + font-weight: 400; + color-scheme: light dark; + color: $color; + background-color: $background-color_dark; + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; + + /* ビヨヨン効果を無効化する 及び スクロール削除 */ + overscroll-behavior: none; + overflow: clip; + overflow-wrap: unset; + overflow-inline: hidden; + padding-top: 0; +} + +#app { + margin: 0 auto; + padding: 0rem; + text-align: center; + +} + +input { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: $font-family_btn; + background-color: $background-color_dark; + transition: border-color 0.25s; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: $font-family_btn; + background-color: $background-color_dark; + transition: border-color 0.25s; +} + +.flex { + display: flex; + padding: 0px; + max-width: 100%; +} + +#file_img_wrapper { + max-width: 100%; + max-height: 100%; + margin-top: auto; + margin-bottom: auto; + background-color: $background-color_dark; +} + +#file_img { + user-select: none; + -webkit-user-drag: none; + -moz-user-select: none; +} + +body { + margin: 0; + display: flex; + place-items: center; + background-color: $background-color_dark; + + /* ビヨヨン効果を無効化する 及び スクロール削除 */ + overscroll-behavior: none; + overflow: clip; + overflow-wrap: unset; + overflow-inline: hidden; + padding-top: 0; +} + +@media (prefers-color-scheme: light) { + @page :root { + color: $color; + background-color: $background-color_dark; + } + + button { + background-color: $background-color_dark; + } +} \ No newline at end of file diff --git a/src/tauri_or_web.ts b/src/tauri_or_web.ts index cac4042..fc1e546 100644 --- a/src/tauri_or_web.ts +++ b/src/tauri_or_web.ts @@ -30,7 +30,7 @@ export function open_file_dialog(load_img: any) { // open_file_dialog_web(load_img) // web } -export function onFileDropEvent(load_img: any) { +export function onFileDropEvent(load_img: any, reset_img_callback: any) { // web // const isValid = (e: any) => e.dataTransfer.types.indexOf("Files") >= 0; // document.body.addEventListener('dragover', (e) => { @@ -59,20 +59,20 @@ export function onFileDropEvent(load_img: any) { console.log('User dropped', ev.payload.paths); const [filepath] = ev.payload.paths// as string[] img_load(convertFileSrc(filepath)) - get_img_src_size(convertFileSrc(filepath), load_img) + get_img_src_size(convertFileSrc(filepath), load_img, reset_img_callback) } }) // tauri end } -export async function listen_img_load(load_img: any) { +export async function listen_img_load(load_img: any, reset_img_callback: any) { // if (load_img) { } // web // tauri await listen('img_load', event => { const msg: string = ((ev: any) => ev.payload.message)(event) if (msg) { img_load(convertFileSrc(msg)) - get_img_src_size(convertFileSrc(msg), load_img) + get_img_src_size(convertFileSrc(msg), load_img, reset_img_callback) } }) // tauri end