diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f38247..7a0655a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,28 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +## [v1.0.1] - 2022.11.15 + +### Fixed + +- 使用手機開啟萬用遙控器輸入文字會刷新畫面,導致無法正常完成操作 + +## [v1.0.0] 2022.11.1 + +### Fixed + +- 平板開啟萬用遙控器時,訊息傳送輸入框消失 +- 平板或手機旋轉後,刷新萬用遙控器 + +### Added + +- 實作萬用遙控器 i18n + +### Changed + +- meta 修改 ## 2022.2.25 @@ -15,4 +37,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Changed - 拿掉 webduinojs 的部份 -- 獨立的 mqttClient.js \ No newline at end of file +- 獨立的 mqttClient.js + +[unreleased]: https://github.com/webduinoio/webduino-remote/compare/v1.0.1...HEAD +[v1.0.1]: https://github.com/webduinoio/webduino-remote/releases/tag/v1.0.1 +[v1.0.0]: https://github.com/webduinoio/webduino-remote/releases/tag/v1.0.0 \ No newline at end of file diff --git a/css/main.css b/css/main.css index 5bf27f7..5a4ef7e 100644 --- a/css/main.css +++ b/css/main.css @@ -53,8 +53,8 @@ body { overflow: hidden; } -.content.loading *{ - opacity:0; +.content.loading * { + opacity: 0; } .panel { @@ -63,7 +63,7 @@ body { height: 100%; top: 0; left: 0; - transition:.3s; + transition: .3s; } /* setting */ @@ -153,13 +153,13 @@ body { background: rgba(100, 200, 255, .3); } -#setting #saveBtn{ +#setting #saveBtn { width: max-content; - font-size:1.2rem; - margin:30px auto 10px; - padding:10px 30px; - background:#e50; - border-radius:20px; + font-size: 1.2rem; + margin: 30px auto 10px; + padding: 10px 30px; + background: #e50; + border-radius: 20px; text-shadow: #900 0 0 5px; } @@ -306,12 +306,14 @@ body { z-index: 2; vertical-align: middle; } -#main01 footer .monster-btn svg{ - transition:.3s; - background:none; + +#main01 footer .monster-btn svg { + transition: .3s; + background: none; } -#main01 footer .monster-btn.click svg{ - width:90%; + +#main01 footer .monster-btn.click svg { + width: 90%; } /* main02 */ @@ -348,7 +350,7 @@ body { color: #ddd; margin: 0 auto; padding: 10px 1rem; - box-shadow:inset #ccc 0 0 0 0, #ccc 0 0 0 3px; + box-shadow: inset #ccc 0 0 0 0, #ccc 0 0 0 3px; border-radius: 10px; border-top-right-radius: 0; border-bottom-right-radius: 0; @@ -358,12 +360,12 @@ body { display: inline-block; font-size: 1.5rem; line-height: 1; - box-shadow:inset #ccc 0 0 0 0, #ccc 0 0 0 3px; + box-shadow: inset #ccc 0 0 0 0, #ccc 0 0 0 3px; border-radius: 10px; background: rgba(255, 255, 255, .1); color: #fff; vertical-align: top; - transition:.3s; + transition: .3s; padding: 10px 1rem; border-top-left-radius: 0; border-bottom-left-radius: 0; @@ -372,26 +374,26 @@ body { #main02 .input-group-button.click { background: rgba(255, 255, 255, .4); - box-shadow:inset #ccc 0 0 0 3px, #ccc 0 0 0 0; + box-shadow: inset #ccc 0 0 0 3px, #ccc 0 0 0 0; } #main02 .btn { display: inline-block; width: 38%; height: 14%; - box-shadow:inset #ccc 0 0 0 0, #ccc 0 0 0 3px; + box-shadow: inset #ccc 0 0 0 0, #ccc 0 0 0 3px; margin: 7px 5px; border-radius: 10px; background: rgba(255, 255, 255, .1); color: #fff; vertical-align: top; -webkit-user-select: none; - transition:.3s; + transition: .3s; } #main02 .btn.click { background: rgba(255, 255, 255, .4); - box-shadow:inset #ccc 0 0 0 3px, #ccc 0 0 0 0; + box-shadow: inset #ccc 0 0 0 3px, #ccc 0 0 0 0; } #main02 .btn::before { @@ -406,7 +408,7 @@ body { display: inline-block; vertical-align: middle; font-size: 1.5rem; - transition:.3s; + transition: .3s; } #main02 .btn.click span { @@ -414,114 +416,139 @@ body { } /* popup */ -#popup{ - top:20%; - left:15%; - width:70%; - height:max-content; - border:3px solid #fff; - z-index:20; - border-radius:20px; - padding:30px 10px; - text-align:center; - background:rgba(50,100,150,.9); - color:#fff; - opacity:0; +#popup { + top: 20%; + left: 15%; + width: 70%; + height: max-content; + border: 3px solid #fff; + z-index: 20; + border-radius: 20px; + padding: 30px 10px; + text-align: center; + background: rgba(50, 100, 150, .9); + color: #fff; + opacity: 0; pointer-events: none; - transition:.3s; + transition: .3s; } -#popup.show{ - top:17%; - opacity:1; + +#popup.show { + top: 17%; + opacity: 1; pointer-events: auto; } -#popup h4{ - font-size:1.1rem; - margin-bottom:10px; + +#popup h4 { + font-size: 1.1rem; + margin-bottom: 10px; } -#saveUrl{ - font-size:1.1rem; - width:100%; - word-wrap:break-word; + +#saveUrl { + font-size: 1.1rem; + width: 100%; + word-wrap: break-word; line-height: 1.5; } -#saveUrl::selection{ - color:#fff; - background:none; + +#saveUrl::selection { + color: #fff; + background: none; } -#copy{ - font-size:1.1rem; - padding:10px 30px; - width:max-content; - margin:20px auto 0; - background:#e50; - border-radius:20px; + +#copy { + font-size: 1.1rem; + padding: 10px 30px; + width: max-content; + margin: 20px auto 0; + background: #e50; + border-radius: 20px; } -#copy.copied{ + +#copy.copied { pointer-events: none; - opacity:.7; + opacity: .7; } -#popupClose{ - position:absolute; - width:40px; - height:40px; + +#popupClose { + position: absolute; + width: 40px; + height: 40px; border-radius: 50%; - border:3px solid #fff; - background:#123; - top:-18px; - right:-18px; + border: 3px solid #fff; + background: #123; + top: -18px; + right: -18px; } + #popupClose::before, -#popupClose::after{ - content:""; - position:absolute; - width:80%; - height:10%; +#popupClose::after { + content: ""; + position: absolute; + width: 80%; + height: 10%; transform-origin: 50% 50%; - background:#fff; - top:45%; - left:10%; + background: #fff; + top: 45%; + left: 10%; } -#popupClose::before{ - transform:rotate(45deg); + +#popupClose::before { + transform: rotate(45deg); } -#popupClose::after{ - transform:rotate(-45deg); + +#popupClose::after { + transform: rotate(-45deg); } /* message */ -#message{ - width:60%; - top:-10px; - left:20%; - height:max-content; - background:rgba(255,255,255,.2); - border:1px dashed #fff; - border-radius:20px; +#message { + width: 60%; + top: -10px; + left: 20%; + height: max-content; + background: rgba(255, 255, 255, .2); + border: 1px dashed #fff; + border-radius: 20px; padding: 0 10px; - opacity:0; - transition:.3s; + opacity: 0; + transition: .3s; pointer-events: none; } -#message.show{ - opacity:1; - top:15px; + +#message.show { + opacity: 1; + top: 15px; } -#message h4{ - color:#fff; - font-size:1.2rem; - text-align:center; - line-height:1.8; +#message h4 { + color: #fff; + font-size: 1.2rem; + text-align: center; + line-height: 1.8; } .noselect { - -webkit-touch-callout: none; /* iOS Safari */ - -webkit-user-select: none; /* Safari */ - -khtml-user-select: none; /* Konqueror HTML */ - -moz-user-select: none; /* Old versions of Firefox */ - -ms-user-select: none; /* Internet Explorer/Edge */ - user-select: none; /* Non-prefixed version, currently + -webkit-touch-callout: none; + /* iOS Safari */ + -webkit-user-select: none; + /* Safari */ + -khtml-user-select: none; + /* Konqueror HTML */ + -moz-user-select: none; + /* Old versions of Firefox */ + -ms-user-select: none; + /* Internet Explorer/Edge */ + user-select: none; + /* Non-prefixed version, currently supported by Chrome, Edge, Opera and Firefox */ +} + +input { + /* Safari 和 Chrome,常用於iOS下移除內建樣式 */ + -webkit-appearance: none; + /* FireFox */ + -moz-appearance: none; + appearance: none; } \ No newline at end of file diff --git a/index-en.html b/index-en.html new file mode 100644 index 0000000..c5fa8d0 --- /dev/null +++ b/index-en.html @@ -0,0 +1,886 @@ + + + + + + + + Webduino Remote Control + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+ +
+
+
+ + +
+
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+

Broadcast Channel

+ + + + + + + + + +
Send
Receive
+
+
+

Monster Broadcast Message

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Middle
Up
Down
Left
Right
Green
Red
Yellow
Blue
+
+
+

Button Broadcast Message

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+
+
Save Shared Link
+
+
+

1234567

+
+ +
+ + + + + + + + + + + diff --git a/index.html b/index.html index a2d9531..3e206fe 100644 --- a/index.html +++ b/index.html @@ -1,46 +1,65 @@ - + + + + + + + Webduino 萬用遙控器 - - - - - - Webduino 萬用遙控器 + + + + + + + + + - - - - - - - - + + - - - - -
- -
- - + +
+ + - -
-
- -
-
-
- - + z M70.5,52.9H54.2v16.2h16.2V52.9z" + /> +
-
- - + +
+
+
+ + +
+
+ + - -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + c-0.3,0-0.5,0.1-0.7,0.3C43,9.3,42.9,9.6,42.9,10.1z" + /> + +
+
+
+
+ + - - + - - - - - - + + + + + + - - - -
-
- - - - - - - - - + + + + + + + + + + + + + + + - - + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - -
-
- - - - - - - - - - - - - - - - - - - - - - + +
+
+ + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + - - - - - + +
+
+ + + + + - - + + + + + - - - -
-
- - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + - - - - - - + + - - + + + + + + + + + + + + + - - - - - - - - + +
+
+
+
+
+
+ +
- -
-
-
- - +
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-

廣播頻道

- - - - - - - - - -
發送
接收
+
+
+

廣播頻道

+ + + + + + + + + +
發送
接收
+
+
+

怪獸廣播訊息

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
小車中間
小車往上
小車往下
小車往左
小車往右
綠色怪獸
紅色怪獸
黃色怪獸
藍色怪獸
+
+
+

按鈕廣播訊息

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
儲存分享連結
-
-

怪獸廣播訊息

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
小車中間
小車往上
小車往下
小車往左
小車往右
綠色怪獸
紅色怪獸
黃色怪獸
藍色怪獸
+
+

1234567

-
-

按鈕廣播訊息

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ -
儲存分享連結
-
-
-

1234567

- -
- - - - - - - - - - + + + + + + + + \ No newline at end of file diff --git a/js/main-en.js b/js/main-en.js new file mode 100644 index 0000000..60ba715 --- /dev/null +++ b/js/main-en.js @@ -0,0 +1,386 @@ +~async function () { + + function handleCustomButton() { + const sendButton = document.querySelector('.input-group-button'); + const customMessage = document.getElementById('customMessage'); + sendButton.addEventListener('click', () => { + mqttPush(list.topic1, customMessage.value); + sendButton.classList.add('click'); + setTimeout(() => { + sendButton.classList.remove('click'); + }, 100); + }); + } + + // 載入 js 之後顯示所有元件 + const content = document.querySelector('.content'); + content.classList.remove('loading'); + + // 凱比機器人和中間的圓形 logo 定位 + const kebbi = document.getElementById('svgKebbi'); + const circle = document.querySelector('.circle'); + function imgPosition() { + const ww = content.offsetWidth; + const wh = content.offsetHeight; + kebbi.style.left = `${(ww - kebbi.offsetWidth) / 2}px`; + kebbi.style.top = `${(wh * 0.8 - kebbi.offsetHeight) / 2}px`; + circle.style.width = `${ww * 0.4}px`; + circle.style.height = `${ww * 0.4}px`; + circle.style.left = `${(ww - circle.offsetWidth) / 2}px`; + circle.style.top = `${(wh * 0.8 - circle.offsetHeight) / 2}px`; + } + + imgPosition(); + + // 預設值 + let list = { + topic1: 'test1', + topic2: 'test2', + kebbiReset: 'reset', + kebbiTop: 'up', + kebbiBottom: 'down', + kebbiLeft: 'left', + kebbiRight: 'right', + svgRed: 'r', + svgGreen: 'g', + svgYellow: 'y', + svgBlue: 'b', + btn0: '1', + btn0n: 'Button 1', + btn1: '2', + btn1n: 'Button 2', + btn2: '3', + btn2n: 'Button 3', + btn3: '4', + btn3n: 'Button 4', + btn4: '5', + btn4n: 'Button 5', + btn5: '6', + btn5n: 'Button 6', + btn6: '7', + btn6n: 'Button 7', + btn7: '8', + btn7n: 'Button 8', + btn8: '9', + btn8n: 'Button 9', + btn9: '10', + btn9n: 'Button 10' + }; + + const urlOrigin = location.origin; + const urlPath = location.pathname; + const urlHash = location.hash.replace('#', ''); + const config = { + databaseURL: "https://webbit-remote.firebaseio.com/" + }; + firebase.initializeApp(config); + const database = firebase.database(); + + /* firebase 存檔 */ + const saveBtn = document.getElementById('saveBtn'); + const popup = document.getElementById('popup'); + const popupClose = document.getElementById('popupClose'); + const saveUrl = document.getElementById('saveUrl'); + popupClose.addEventListener('click', () => { + popup.classList.remove('show'); + }); + saveBtn.addEventListener('click', async function () { + let t = new Date(); + list.time = `${t.getFullYear()}/${t.getMonth() * 1 + 1}/${t.getDate()} ${t.getHours()}:${t.getMinutes()}:${t.getSeconds()}`; + let write = await database.ref('/').push(list); + popup.classList.add('show'); + let url = `${urlOrigin}${urlPath}#${write.key}`; + saveUrl.innerText = url; + window.history.pushState({}, 0, url); + document.getSelection().removeAllRanges(); + }); + + // 點擊後複製連結 + const copy = document.getElementById('copy'); + new ClipboardJS('#copy'); + copy.addEventListener('click', () => { + copy.innerText = 'Copy Successfully!'; + copy.classList.add('copied'); + setTimeout(() => { + copy.innerText = 'Copy link'; + copy.classList.remove('copied'); + }, 1000); + }); + + /* firebase 讀檔 */ + if (urlHash) { + list = await database.ref(urlHash).once('value').then(result => { + return result.val(); + }); + save(list); + } else { + // 讀取 localStorage 資料,沒有的話就套用預設值 + let read = JSON.parse(localStorage.getItem('kebbiMobileEnData')); + if (read) { + list = read; + } + } + + // 點擊選單按鈕開啟選單 + const setting = document.getElementById('setting'); + const menu = document.getElementById('menu'); + menu.addEventListener('click', () => { + setting.classList.toggle('open'); + menu.classList.toggle('close'); + window.scrollTo(0, 0); + }); + + // 兩種控制器互相切換 + const s1 = document.getElementById('s1'); + const s2 = document.getElementById('s2'); + const main01 = document.getElementById('main01'); + const main02 = document.getElementById('main02'); + s1.addEventListener('click', () => { + s1.classList.add('hide'); + main01.classList.add('hide'); + s2.classList.remove('hide'); + main02.classList.remove('hide'); + }); + s2.addEventListener('click', () => { + s2.classList.add('hide'); + main02.classList.add('hide'); + s1.classList.remove('hide'); + main01.classList.remove('hide'); + }); + + + // 顯示十顆按鈕的文字 + const btn = document.querySelectorAll('.btn'); + let btnObj = {}; + btn.forEach(e => { + btnObj[e.id] = document.getElementById(e.id); + e.innerHTML = `${list[e.id]}`; + }); + + // 暫存到 localStorage 的函式 + function save(val) { + localStorage.setItem('kebbiMobileEnData', JSON.stringify(val)); + } + + // input 欄位套用預設值 + const input = document.querySelectorAll('input'); + input.forEach(e => { + let self = e; + let m = self.getAttribute('m'); + self.value = list[m]; + self.addEventListener('input', () => { + window.history.pushState({}, 0, `${urlOrigin}${urlPath}`); + list[m] = self.value; + if (btnObj[m]) { + btnObj[m].innerHTML = `${self.value}`; + } + save(list); + if (m == 'topic2') { + mqttGet(list.topic2); + } + }); + }); + + // 連接 mqtt server + let webduinoBroadcastor; + if (!webduinoBroadcastor) { + webduinoBroadcastor = new window.mqttClient(); + try { + await webduinoBroadcastor.connect(); + } catch (err) { + console.error(err); + } + } + // 發送 mqtt 訊號 + const mqttPush = function (topic, msg) { + if (topic == list.topic1) { + webduinoBroadcastor.send({ + topic: topic, + message: (msg).toString() + }); + } + } + // 接收 mqtt 訊號 + const message = document.getElementById('message'); + const messageH4 = document.querySelector('#message h4'); + let messageTimer; + const mqttGet = async function (topic) { + await webduinoBroadcastor.onMessage(topic, async (msg) => { + if (topic == list.topic2) { + clearTimeout(messageTimer); + messageH4.innerText = msg; + message.classList.add('show'); + messageTimer = setTimeout(() => { + message.classList.remove('show'); + }, 3000); + } + }); + } + mqttGet(list.topic2); + + // 下方怪獸按鈕點擊事件 + const monsterBtn = document.querySelectorAll('.monster-btn'); + monsterBtn.forEach(e => { + let self = e; + self.addEventListener('click', () => { + mqttPush(list.topic1, list[self.id]); + self.classList.add('click'); + setTimeout(() => { + self.classList.remove('click'); + }, 100); + }); + }); + + // 十顆按鈕點擊事件 + btn.forEach(e => { + let self = e; + let msg = self.getAttribute('msg'); + self.addEventListener('click', () => { + mqttPush(list.topic1, list[msg]); + self.classList.add('click'); + setTimeout(() => { + self.classList.remove('click'); + }, 100); + }); + }); + + handleCustomButton(); + + let send = { + center: false, + top: false, + bottom: false, + left: false, + right: false + }; + function sendCheck(type) { + send = { + center: false, + top: false, + bottom: false, + left: false, + right: false + }; + if (type) { + send[type] = true; + } + } + + // Kebbi 拖曳事件 + drag(); + function drag() { + let drag = false; + let mx, my, dx, dy, carSize; + + function move(evt) { + let touches = evt.changedTouches; + if (touches) { + mx = ~~touches[0].pageX; + my = ~~touches[0].pageY; + } else { + mx = evt.pageX; + my = evt.pageY; + } + if (drag) { + kebbi.style.left = mx - dx + 'px'; + kebbi.style.top = my - dy + 'px'; + } + if (kebbi.classList.contains('target')) { + const kx = kebbi.offsetLeft; // 車子 left + const ky = kebbi.offsetTop; // 車子 top + const carSize = getCarSize(); + + // 注意,小車一開始的中心點 y 座標,不等於畫面的中心點 y 座標。 + // 邊界在中心的周圍 1/3 小車寬/高的距離 + const kxCenter = kx + carSize.width / 2; // 車子中心點 x 座標 + const kyCenter = ky + carSize.height / 2; // 車子中心點 y 座標 + const leftSide = content.offsetWidth * 0.5 - carSize.width / 3; // 左邊界,小於這個值,判定車子移動到左邊 + const rightSide = content.offsetWidth * 0.5 + carSize.width / 3; // 右邊界,大於這個值,判定車子移動到右邊 + const topSide = (content.offsetHeight * 0.8 - kebbi.offsetHeight) / 2 + carSize.height / 6; // 上邊界,小於這個值,判定車子移動到上面 + const bottomSide = (content.offsetHeight * 0.8 - kebbi.offsetHeight) / 2 + 5 * carSize.height / 6; // 下邊界,小於這個值,判定車子移動到下面 + + if (kxCenter < leftSide) { + if (!send.left) { + sendCheck('left'); + mqttPush(list.topic1, list.kebbiLeft); + } + } else if (kxCenter > rightSide) { + if (!send.right) { + sendCheck('right'); + mqttPush(list.topic1, list.kebbiRight); + } + } else { + if (kyCenter < topSide) { + if (!send.top) { + sendCheck('top'); + mqttPush(list.topic1, list.kebbiTop); + } + } else if (kyCenter > bottomSide) { + if (!send.bottom) { + sendCheck('bottom'); + mqttPush(list.topic1, list.kebbiBottom); + } + } else { + if (!send.center) { + sendCheck('center'); + mqttPush(list.topic1, list.kebbiReset); + } + } + } + } + } + + function target(evt) { + evt.preventDefault(); + kebbi.classList.remove('reset'); + let touches = evt.changedTouches; + if (touches) { + mx = ~~touches[0].pageX; + my = ~~touches[0].pageY; + } + drag = true; + dx = mx - kebbi.offsetLeft; + dy = my - kebbi.offsetTop; + kebbi.classList.add('target'); + updateCarSize(); + sendCheck('center'); // 設定初始狀態為 center + } + + function reset() { + if (send.top || send.bottom || send.left || send.right) { + console.log('reset'); + mqttPush(list.topic1, list.kebbiReset); + } + sendCheck(); + drag = false; + kebbi.classList.remove('target'); + kebbi.classList.add('reset'); + kebbi.style.left = `${(content.offsetWidth - kebbi.offsetWidth) / 2}px`; + kebbi.style.top = `${(content.offsetHeight * 0.8 - kebbi.offsetHeight) / 2}px`; + } + + function updateCarSize() { + const car = document.getElementById('svgKebbi'); + carSize = { + width: car.offsetWidth, + height: car.offsetHeight, + }; + } + + function getCarSize() { + return carSize; + } + + document.addEventListener('mousemove', move); + document.addEventListener('mouseup', reset); + kebbi.addEventListener('mousedown', target); + + kebbi.addEventListener('touchmove', move); + kebbi.addEventListener('touchend', reset); + kebbi.addEventListener('touchstart', target); + } + + // 處理中間圖片跟隨視窗大小移動位置 + window.addEventListener('resize', imgPosition); + +}(); diff --git a/js/main.js b/js/main.js index 7206b09..011b7f9 100644 --- a/js/main.js +++ b/js/main.js @@ -19,16 +19,18 @@ // 凱比機器人和中間的圓形 logo 定位 const kebbi = document.getElementById('svgKebbi'); const circle = document.querySelector('.circle'); - const ww = content.offsetWidth; - const wh = content.offsetHeight; - const ox = (ww - kebbi.offsetWidth) / 2; - const oy = (wh * 0.8 - kebbi.offsetHeight) / 2; - kebbi.style.left = `${ox}px`; - kebbi.style.top = `${oy}px`; - circle.style.width = `${ww * 0.4}px`; - circle.style.height = `${ww * 0.4}px`; - circle.style.left = `${(ww - circle.offsetWidth) / 2}px`; - circle.style.top = `${(wh * 0.8 - circle.offsetHeight) / 2}px`; + function imgPosition() { + const ww = content.offsetWidth; + const wh = content.offsetHeight; + kebbi.style.left = `${(ww - kebbi.offsetWidth) / 2}px`; + kebbi.style.top = `${(wh * 0.8 - kebbi.offsetHeight) / 2}px`; + circle.style.width = `${ww * 0.4}px`; + circle.style.height = `${ww * 0.4}px`; + circle.style.left = `${(ww - circle.offsetWidth) / 2}px`; + circle.style.top = `${(wh * 0.8 - circle.offsetHeight) / 2}px`; + } + + imgPosition(); // 預設值 let list = { @@ -167,7 +169,7 @@ let m = self.getAttribute('m'); self.value = list[m]; self.addEventListener('input', () => { - window.history.pushState({}, 0, urlOrigin); + window.history.pushState({}, 0, `${urlOrigin}${urlPath}`); list[m] = self.value; if (btnObj[m]) { btnObj[m].innerHTML = `${self.value}`; @@ -287,15 +289,14 @@ const kx = kebbi.offsetLeft; // 車子 left const ky = kebbi.offsetTop; // 車子 top const carSize = getCarSize(); - // 注意,小車一開始的中心點 y 座標,不等於畫面的中心點 y 座標。 // 邊界在中心的周圍 1/3 小車寬/高的距離 - const kxCenter = kx + carSize.width/2; // 車子中心點 x 座標 - const kyCenter = ky + carSize.height/2; // 車子中心點 y 座標 - const leftSide = ww * 0.5 - carSize.width/3; // 左邊界,小於這個值,判定車子移動到左邊 - const rightSide = ww * 0.5 + carSize.width/3; // 右邊界,大於這個值,判定車子移動到右邊 - const topSide = oy + carSize.height/6; // 上邊界,小於這個值,判定車子移動到上面 - const bottomSide = oy + 5 * carSize.height/6; // 下邊界,小於這個值,判定車子移動到下面 + const kxCenter = kx + carSize.width / 2; // 車子中心點 x 座標 + const kyCenter = ky + carSize.height / 2; // 車子中心點 y 座標 + const leftSide = content.offsetWidth * 0.5 - carSize.width / 3; // 左邊界,小於這個值,判定車子移動到左邊 + const rightSide = content.offsetWidth * 0.5 + carSize.width / 3; // 右邊界,大於這個值,判定車子移動到右邊 + const topSide = (content.offsetHeight * 0.8 - kebbi.offsetHeight) / 2 + carSize.height / 6; // 上邊界,小於這個值,判定車子移動到上面 + const bottomSide = (content.offsetHeight * 0.8 - kebbi.offsetHeight) / 2 + 5 * carSize.height / 6; // 下邊界,小於這個值,判定車子移動到下面 if (kxCenter < leftSide) { if (!send.left) { @@ -353,8 +354,8 @@ drag = false; kebbi.classList.remove('target'); kebbi.classList.add('reset'); - kebbi.style.left = `${ox}px`; - kebbi.style.top = `${oy}px`; + kebbi.style.left = `${(content.offsetWidth - kebbi.offsetWidth) / 2}px`; + kebbi.style.top = `${(content.offsetHeight * 0.8 - kebbi.offsetHeight) / 2}px`; } function updateCarSize() { @@ -378,4 +379,7 @@ kebbi.addEventListener('touchstart', target); } + // 處理中間圖片跟隨視窗大小移動位置 + window.addEventListener('resize', imgPosition); + }();