0%

前言

最近要在 expo 專案加上相機功能,由於會調用到 native api,必須重新安裝 dev client
又因為相機功能不能在 emulator 測試,所以必須想辦法裝在 iphone 上
簡單紀錄一下做法

步驟

  1. 下載 xcode 並更新到最新版本

  2. 開啟 iPhone 的開發者模式(需要重啟手機)
    設定 > 隱私權與安全性 > (滑到最下面)開發者模式

  3. 把 iPhone 用 USB 連接上電腦
    除了插線,也要記得解鎖手機按允許連接

  4. 照著 這些步驟 設定簽證,過程中會要求登入 apple 帳號

  5. 打包 app 並安裝到手機上
    npx expo run:ios -d
    -d 代表要選擇裝置。然後 expo 會做出一個 ios 資料夾,安裝所需的東西

  6. 選擇實體裝置(透過 USB 連上的 iPhone),便會開始 build 並安裝到手機上

  7. 前兩步驟如果遇到問題,可以改用 Xcode 開啟專案直接 build
    build 之前如果還沒有 ios 資料夾,可以用 npx expo prebuild -p ios 生成一個

  8. 安裝過程中會需要輸入兩次密碼

  9. 完成

小發現

意外得知其實 emulation 跟 simulation 不一樣
中文雖然都叫模擬
但 emulation 的意思是在一個系統下運行另一個系統,達到模擬
simulation 則是建立理論模型後去預測結果,這也是模擬

所以像前述的 iPhone 模擬器就是在電腦系統下去運行 iOS 系統,是 emulator

前言: 如何顯示 svg 圖檔

關於怎麼在 react 專案中顯示 svg
有下列幾種方法

  1. 用 img 元素顯示
  2. 利用 SVGR 線上轉換器,將 svg 轉換成 tsx 版本
  3. 安裝 SVGR plugin,直接在專案中 import svg 就能用

1. 用 img 元素顯示

1
2
3
4
5
6
// 直接放路徑
<img src={"./ic-close.svg"} />;

// 也可以import後再放
import CloseIcon from "./ic-close.svg";
<img src={CloseIcon.src} />;

2. 利用 SVGR 線上轉換器,將 svg 轉換成 tsx 版本

1
2
3
4
<!-- before -->
<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3.40137 3.3999L13.6014 13.5999M13.6014 3.3999L3.40137 13.5999" stroke="white" stroke-opacity="0.8" stroke-width="2" stroke-linecap="round"/>
</svg>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// after
import * as React from "react";
const SvgComponent = (props) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width={17}
height={17}
fill="none"
{...props}
>
<path
stroke="#fff"
strokeLinecap="round"
strokeOpacity={0.8}
strokeWidth={2}
d="m3.401 3.4 10.2 10.2m0-10.2-10.2 10.2"
/>
</svg>
);
export default SvgComponent;

3. 安裝 SVGR plugin,直接在專案中 import svg 就能用

安裝方法請見 https://react-svgr.com/docs/next/

1
2
3
4
5
import Icon from './ic-close.svg'

...

<Icon/>

前言: 如何動態調整 svg 的顏色

1. 手動編輯 svg 裡的 fill 或 stroke 屬性,改為 currentColor

1
2
3
<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3.40137 3.3999L13.6014 13.5999M13.6014 3.3999L3.40137 13.5999" stroke="currentColor" stroke-opacity="0.8" stroke-width="2" stroke-linecap="round"/>
</svg>

2. 調整 SVGR 套件的設定,讓他再轉譯的過程中自動把某個顏色(例如#ffffff)換成 currentColor

細節請見:https://react-svgr.com/docs/options/#replace-attribute-value

如何用<img>顯示卻又能動態調整顏色

這次遇到的狀況是:
我要開發手機版網頁的 bottom nav bar,長這個樣子

由於這些按鈕必須和桌面版的 header nav bar 同步
秉持 single source of truth 的原則
我先建一個 json,然後在兩處 UI insert value,來決定要顯示什麼圖、文字跟點擊後去到的路徑

1
2
3
4
5
6
7
8
9
10
11
12
13
// NavRoutes.json
[
{
"title": "Product",
"href": "/",
"icon": "ic-product.svg"
},
{
"title": "Bridge",
"href": "/bridge",
"icon": "ic-bridge.svg"
}
]
1
2
3
4
5
6
7
import NavRoutes from 'NavRoutes.json'
import Image from 'next/image'

...
{NavRoutes.map(route=>(
<Image src={route.icon}/>
))}

問題是這樣就無法利用 currentColor 來調整顏色了
我還要讓網頁所在的按鈕亮起來才行

以 svg 來說因為檔案很小
其實我可以準備兩份顏色不同的 icon
在 active/inactive 之間切換就好
但我還是好奇有沒有更省事的做法
於是找到這個討論
發現一個蠻酷的做法

它的原理是利用 CSS 的 filter 屬性改變圖片的顏色
只是這個轉換過程不好計算,所幸有人已經寫好轉換工具
唯一要注意的是這個轉換必須從黑色開始
要嘛轉換前先把 svg 手動改成黑色
不然就是在 css filter 開頭加上 brightness(0) saturate(100%) 也行

References

前言

最近安裝 highcharts 來試玩,因為之後公司的網頁有可能會換圖表套件,想要找一個比現在用的 lightweight chart 再更靈活一點的,畢竟他的主力是在 financial charts,拿來做股市圖蠻不錯的,但圖表類型很少連圓餅圖都沒有。

研究的過程中遇到一個 type error 覺得蠻有意思的。

想要從圖表提取 x, y 以外的資料

我想要做的功能是:當滑鼠指到圖上的任一點,圖表外的某處就要顯示該點的 x,y 值,以及另一個附加的資料。類似下面這樣(lightweight chart)

這張圖看起來不就是把 y 值提出來而已嗎?這樣有什麼困難?但其實我背後是把 y 值設為幣價的絕對值,以此來做圖。至於 y 軸會變成百分比是因為 lightweight chart 有提供一個功能讓我可以用百分比來顯示。

現在我要用 highcharts 做到一樣的事情,在設定 data property 時應用物件的方式定義 x,y 以及額外的資料,而不是用陣列的方式定義,請看以下

1
2
3
4
5
6
7
8
9
10

const options {
data: [[1,20,'extra1'], [2,23,'extra2'], [3,19,'extra3']], //不要這樣定義
data: [
{x: 1, y: 20, extra: 'extra1'},
{x: 2, y: 23, extra: 'extra2'},
{x: 3, y: 19, extra: 'extra3'}
] //應該這樣定義
}

這樣一來就可以用series.point.event.mouseover觸發 hover event ,再藉由 callback function 裡的this去取值,但這就遇到 Typescript 的問題了

如果 this 跟想像的不一樣怎麼辦

我想這是因為我定義了額外的屬性,雖然 highcharts 好心的幫我加進去 this,但是新的AUM屬性就是不存在在this的type(實際上是Highcharts.Point)裡面啊,但我要怎麼讓這個 type error 消失啊?

optional chaining 不行,this 也不能 assign 到別的變數(no-this-alias error)

研究好一段時間之後,這樣就可以了:

1
2
3
{
AUM: (this as typeof this & { AUM: string }).AUM
}

結論

一般來說遇到這種問題應該要去修改最根本的 type 定義,但今天遇到的是特殊狀況,我要怎麼從源頭修改 this 的 type 啊?
現在終於知道原來可以在 dot notation 前面用括號刮起來用as,又多知道一個應急的方法了