2019年12月28日

[Vue] 整合 Vue style guide, eslint-plugin-vue 和 VSCode

Vue Style Guide 中對於 Vue 專案的程式風格提供了許多建議,但有些時候在撰寫程式時還需要額外留意這些撰寫風格反而變成一種負擔,好在這時候 Vue 提供了好用的 eslint-plugin-vue (@vue/cli-plugin-eslint),透過 eslint 可以幫我們檢查哪些程式碼中的內容是不符合 Style Guide 所建議的,並且予以修正。
同時搭配上 VSCode 後,可以在存檔後自動根據 eslint 的建議來重新編排程式碼,不只省下了許多需要調整撰寫風格的認知負擔,更重要的是省下了許多時間,可以專注在程式開發上。
在這篇文章中就說明如何根據 Vue Style Guide 一併整合 eslint-plugin-vue 與 VSCode。

安裝 eslint-plugin-vue

建立專案

這裡快速的透過 Vue CLI 的工具快速建立專案:
# 這裡使用的 Vue CLI 版本為 4.2.3
$ vue create vue-eslint-sandbox

安裝用於 Vue 的 eslint 設定檔套件

接著透過 Vue CLI 安裝 eslint-plugin-vue:
# 若要直接透過 npm 安裝,可以參考官方說明
$ vue add @vue/cli-plugin-eslint
接著會請你選擇要使用的 ESLint 設定檔,這裡可以根據團隊或自己撰寫 JavaScript 的習慣去選擇,舉例來說這裡選擇 Standard(也就是 Standard JS 的風格規範):
Imgur
接著會進一步詢問有沒有需要額外個功能。這裡我只選第一項:
eslint-plugin-vue

設定 eslint 並修改程式碼

預設 cli-plugin-eslint 會把 ESLint 的設定檔寫在 package.json 中的 eslintConfig 欄位,像是這樣:
// package.json
{
  "name": "vue-eslint-sandbox",
  // ...
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended",
      "@vue/standard"
    ],
    "parserOptions": {
      "parser": "babel-eslint"
    },
    "rules": {}
  },
  // ...
}
Vue 的程式碼撰寫風格中可以分成幾種不同的嚴謹度,分別是 base, essential, strongly-recommended, 和 recommended
{
  "extends": "plugin:vue/base",         // 受到的規範最少
  "extends": "plugin:vue/essential",
  "extends": "plugin:vue/strongly-recommended",
  "extends": "plugin:vue/recommended"   // 最嚴謹,完全依照建議
}
簡單來說,plugin:vue/recommended 會套用幾乎所有在 Vue Style Guide 中的建議,因此會使用到最多規則,也最不用自己動腦調整,其次是 plugin:vue/strongly-recommended,如果你希望受到 Vue Style Guide 的規範最少,則可以選 plugin:vue/base
關於每一項設定的詳細規則可以參考 eslint-plugin-vue rules 的說明。
可以選擇你希望遵守的嚴謹程度,修改在 package.json 中的 eslintConfig 中的 extends 當中的值。

補充:使用 eslint 設定檔(可略過)

ESLint 除了可以解析 package.json 中對於 ESLint 的設定外,也可以建立額外的 ESLint 設定檔。因此,如果你不想把 ESLint 的設定存放在 package.json 中的話,也可以把 eslintConfig 的欄位移除,額外在根目錄建立一隻 .eslintrc.js 的檔案,如同下面所述。
先在根目錄的地方建立 .eslintrc.js 檔,在這支檔案可以根據你的需求進行設定:
// ./.eslintrc.js
module.exports = {
  extends: [
    // 在這裡可以添加你想要使用的風格規範,例如:
    // 'eslint:recommended',
    'plugin:vue/recommended'
  ],
  rules: {
    // 在這裡可以針對特定的規則進行覆蓋或添加,例如
    // 'vue/no-unused-vars': 'error'
  }
}
其中 extends 的部分一樣有幾種選項可以根據自己或專案的需要進行調整:
// ./.eslintrc.js
{
  "extends": "plugin:vue/base",         // 受到的規範最少
  "extends": "plugin:vue/essential",
  "extends": "plugin:vue/strongly-recommended",
  "extends": "plugin:vue/recommended"   // 最嚴謹,完全依照建議
}
另外,因為這裡使用的是 Standard JS 的撰寫風格(vue/standard),並希望使用 ESLint 提供的建議(eslint:recommended),所以另外添加兩個規範;同時,因為專案中會使用到較新版本的 JavaScript 語法,因此需要定義 parserOptions 以使用比較新的 JavaScript 語法。最後的 .eslintrc.js 會長像這樣子:
// ./.eslintrc.js

module.exports = {
  root: true,
  env: {
    node: true
  },
  extends: [
    // add more generic rulesets here, such as:
    'eslint:recommended',
    'plugin:vue/recommended',
    '@vue/standard'
  ],
  rules: {
    // override/add rules settings here, such as:
    // 'vue/no-unused-vars': 'error'
  },
  parserOptions: {
    parser: 'babel-eslint'
  }
}

執行 eslint 修改程式碼

剛剛我們透過 Vue CLI 安裝好 eslint-plugin-vue 之後,預設它會在 package.json 中添加了 lint 的指令,因此現在可以在終端機直接執行 npm run lint
$ npm run lint
執行後,會自動修改程式碼的撰寫風格,可以看到原本的檔案已經被調整成符合 Vue Style Guide 的建議,並且自動存檔
plugin-eslint-vue
同時,終端機也會列出所有不符合 Vue Style Guide 規範的部分,也就是需要人工調整的部分:
eslint-plugin-vue
這個警告很明顯的是在 Vue Style Guide 的 Prop definitions 中有提到,希望 Props 能盡量定義的詳細,這裡因為沒有告知 msg 這個屬性是 required 的,表示這個 props 有可能不存在,因此它會建議你要帶入預設值。
因此只需要把原本 HelloWord.vue 的程式碼根據建議加上預設值(default):
<!-- ./src/components/HelloWorld.vue  -->
<template>
  <!-- ... --->
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: {
      type: String,
      default: 'Hello Vue'
    }
  }
}
</script>
存檔後再執行一次 npm run lint 則顯示沒有任何錯誤!
eslint-plugin-vue
透過 npm run lint 之後,eslint-plugin-vue 會自動幫我們修正程式碼撰寫風格、HTML 標籤內的屬性順序、Vue 方法的排序等等都調整成 Vue Style Guide 的建議並存檔。但有些部分是它沒辦法自動處理的,這時候還是需要回去檢視這些部分。要留意的是,這些部分不去修正不代表你的程式碼會無法正確執行,而是沒有符合 Vue 的建議,而這些建議之所以存在,通常就是為了提升程式碼的可維護性和減少看能犯錯的機會。

整合 VS Code

最後,由於每次都要執行 npm run lint 稍微還有些麻煩,我們可以把 eslint 直接整合在 VSCode 中,當存檔的時候,就會自動轉換成建議的 Vue Style Guide 的撰寫風格。

安裝 Vue 和 Eslint 套件

Vetur

Vetur 套件可以算是在使用 VS Code 撰寫 Vue 時必配的套件,最明顯的是沒有它的話在撰寫 .vue 的時候程式碼不會有高亮的效果,但它實際上還做了很多其他的事。
vetur

ESLint

接著要安裝微軟官方提供的 ESLint 這個套件來將 VS Code 和 ESLint 整合在一起。
eslint

設定 settings.json

打開 settings.json 設定頁

首先進入 VSCode 的設定頁(MAC 可以按快捷鍵 CMD + ,):
imgur
因為現在 VSCode 預設是使用 UI 的方式進行設定,若想要直接編輯 settings.json 檔,可以在搜尋欄中搜尋 launch 然後點選在 settings.json 內編輯:
settings.json
接著就可以看到 settings.json 的檔案:
settings.json

添加相關設定

settings.json 中加入下面的設定,讓 eslint 可以針對 .vue 檔進行檢驗(預設只會針對 .js.jsx 的檔案):
// VSCode settings.json
{
  "eslint.alwaysShowStatus": true,
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact",
    "vue",
  ],
}
同時,如果你希望存檔時可以自動排版,則可以加上:
// VSCode settings.json
{
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
}
另外,因為安裝了 ESLint,因此就不需要 Vetur 針對 template 提供的驗證,一樣在 settings.json 加上如下的設定:
// VSCode settings.json
{
  "vetur.validation.template": false
}
完整的 settings.json 檔案如下:
// VSCode settings.json
{
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  "eslint.alwaysShowStatus": true,
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact",
    "vue",
  ],
  "vetur.validation.template": false,
}

大功告成

到這裡就大功告成了,只要在你想按下存檔的時候,VS Code 就會自動根據 ESLint 中的設定重新排版程式畫面,若有警告或錯誤的程式碼,則會在程式碼下方以波浪符號提示:
eslint-plugin-vue

參考資源

2019年12月6日

[WebAPIs] Picture In Picture of Video

keywords: video, WebAPIs

TL;DR

新技術一定有風險,瀏覽器有支援有不支援(目前只有 Chrome 預設是支援的),使用前應詳閱公開說明書!
// 檢驗瀏覽器有無支援 Picture In Picture API
if ('pictureInPictureEnabled' in document) {
  // 有支援...
}

// 進入 video 的 PIP 模式
videoElement.requestPictureInPicture().catch((error) => {
  // 錯誤處理...
});

// 離開 video 的 PIP 模式
document.exitPictureInPicture().catch((error) => {
  // Error handling
});
這篇文章內容主要整理自 An Introduction to the Picture-in-Picture Web API @ CSS Tricks

Picture In Picture 是什麼?

Video 元素的 Picture in Picture 模式可以讓影片獨立出來播放(下圖上方),甚至可以在其他頁籤繼續觀看原本的影片(下圖下方):
Imgur

進入和離開 Picture In Picture

// 進入 Picture In Picture
videoElement.requestPictureInPicture().catch((error) => {
  // Error Handling
});

// 離開 Picture In Picture
document.exitPictureInPicture().catch((error) => {
  // Error Handling
});

事件(Events)

videoElement.addEventListener('enterpictureinpicture', () => {
  notice.textContent = 'Enter Picture-in-Picture mode';
});

videoElement.addEventListener('leavepictureinpicture', () => {
  notice.textContent = 'Exit Picture-in-Picture mode';
});

在 PIP 的視窗上測做或增加功能鍵

只要透過 navigator.mediaSession.setActionHandler 就可以在 PIP 的視窗上操作不同的功能鍵:
// 當使用者點擊特定操作鍵時
navigator.mediaSession.setActionHandler('play', function() {
  // User clicked "Play" button.
});
navigator.mediaSession.setActionHandler('pause', function() {
  // User clicked "Pause" button.
});

同時也可以增加原本上面沒有顯示的功能鍵:
// 在 PIP 的視窗上增加前一部、後一部的功能鍵
navigator.mediaSession.setActionHandler('previoustrack', () => {
  // Go to previous track
});

navigator.mediaSession.setActionHandler('nexttrack', () => {
  // Go to next track
});
Imgur

在使用者前鏡頭的畫面呈現於 PIP 上

同樣地,也可以將裝置前置鏡頭的畫面呈現於 PIP 的視窗上,程式碼的部分可以參考 CSS Tricks 上的這個 CodePen:
## 避免瀏覽器使用 PIP 功能
在 HTML 的 <video> 標籤中加入 disablePictureInPicture 即可:
<video disablePictureInPicture controls src="video.mp4>"></video>

程式範例

參考資料

2019年11月20日

[WebAPIs] Web Share API 的使用 - navigator.share

keywords: WebAPIs, mobile, navigator.share

TL;DR

// 判斷瀏覽器是否支援 Web Share API
if (navigator.share) {
  // navigator.share 會回傳 Promise
  navigator.share({
    title: 'Web Fundamentals',
    text: 'Check out Web Fundamentals — it rocks!',
    url: 'https://developers.google.com/web',
  })
  .then(() => console.log('Successful share'))
  .catch((error) => console.log('Error sharing', error));
}

Web Share API 的說明

用手機瀏覽網頁的時候,不知道你有沒有注意過,當你按下分享按鈕時它會跳出一個選單,讓你可以選擇要分享到哪個 App 的選單,像是這樣:
Web Share API
這個功能過去需要透過點擊手機瀏覽器上的「分享」後才會出現:
Web Share API
但現在透過 Web Share 這個 API 也可以輕鬆達到這個功能,讓使用者在點擊網頁上的按鈕後就跳出這個「分享選單」,如此就有機會省去使用那種帶有一堆 Facebook、Line、Twitter、Pinterest 按鈕的第三方套件,進一步減少頁面載入時間。
現在就來看看怎麼使用吧!

Web Share API - navigator.share

適用瀏覽器

Web Share API 的使用方式很簡單,但要注意的是這主要是適用在手機上的功能,畢竟電腦上沒有這種分享選單(目前除了 Mac 的 Safari 可用),不過即使電腦不支援此 API 的使用,還是可以很容易做出替代方案(fallback)。
看到下圖瀏覽器支援性的一大片紅字感覺很恐怖,但目前(2019-11-20)其實主要的手機瀏覽器(Chrome, Safari)都適用,Mac 上的 Safari 亦可:
Web Share API
目前實測在三星內建的瀏覽器上可以使用,但分享成功後的回傳訊息不太正確。

使用方式

使用方式很簡單:
// navigator.share 會回傳一個 Promise

// 下面的欄位可以不用全部填寫,可以只分享網址,也可以只分享文字
const sharePromise = navigator.share({
  url: 'https://pjchender.blogspot.com',    // 要分享的 URL
  title: 'PJCHENder 那些沒告訴你的小細節',      // 要分享的標題
  text: '好多眉眉角角啊'             // 要分享的文字內容
});
navigator.share() 會回傳一個 Promise (代表你可以搭配 async...await 使用),這個 Promise 會在使用者完成點擊某個 App 分享後被完成(fulfilled);若使用者取消分享或帶入的參數有錯誤時,則會被拒絕(reject)。
使用時有幾點需留意一下:
  1. Web Share API 只能使用在有 HTTPS 的網站或者是測試時的 localhost,若想玩玩看這個 API 就可以到帶有 HTTPS 的 CodePen 上試試看。
  2. 需要透過使用者主動的行爲(user activation)才能觸發,例如,點擊事件。

範例程式碼

來看一下範例程式碼吧,也可以直接看 CodePen
See the Pen Web Share API by PJCHEN (@PJCHENder) on CodePen.

HTML

先建立最基本的一個按鈕:
<div class="center-center">
  <button>Share<i class="fas fa-share-alt"></i></button>
  <p class="result"></p>
</div>

JavaScript

  1. 透過 document.querySelector() 選擇和 DOM 有關的元素
  2. 建立使用者點擊分享時要帶入的資訊,不用每一項都填寫,也可以只分享文字或網址
  3. Web Share API 需要使用者主動的行為才能觸發, 所以透過 addEventListener 監聽使用者點擊 click 事件
  4. 透過 navigator.share 來使用 Web Share API
  5. 當使用者拒絕分享或發生錯誤時要顯示的訊息
// STEP 1:選擇和 DOM 有關的元素
const btn = document.querySelector('button');
const result = document.querySelector('.result');

// STEP 2:建立使用者點擊分享時要帶入的資訊
const shareData = {
  url: 'https://pjchender.blogspot.com', // 要分享的 URL
  title: 'PJCHENder 那些沒告訴你的小細節', // 要分享的標題
  text: '好多眉眉角角啊', // 要分享的文字內容
};

// STEP 3:當使用者點擊按鈕時
btn.addEventListener('click', async () => {
  try {
    // STEP 4:使用 Web Share API
    await navigator.share(shareData);
    result.textContent = '感謝你的的分享';
  } catch (err) {
    // STEP 5:使用者拒絕分享或發生錯誤
    const { name, message } = err;
    if (name === 'AbortError') {
      result.textContent = '您已取消分享此訊息';
    } else {
      result.textContent = err;
      console.log('發生錯誤', err);
    }
  }
});
如此就完成這個簡單的範例了。
這個範例的按鈕樣式是修改自 AyooluwaCodePen
來看一下實作的結果:
Web Share API
以 Line 為例,傳送出去的訊息內容如下:
Web Share API
See the Pen Web Share API by PJCHEN (@PJCHENder) on CodePen.

替代處理與其他(fallback)

對於不支援 Web Share API 的瀏覽器則可以透過判斷 navigator.share 是否存在來進行替代方案:
if (navigator.share) {
  // 使用 Web Share API
} else {
  // 替代方案寫在這...
}
舉例來說,在 CSS Tricks 的 How to Use the Web Share API 文章中提供了非常精緻的替代處理畫面:
Imgur
可以參考這個作者的 CodePen 範例。
如果不想這麼複雜的話,替代方案也可以是點擊按鈕後複製網址(Copy Link)給使用者自行分享即可。複製到剪貼簿的方式同樣有對應的 WebAPIs 可以支援,有需要可以參考先前整理的筆記 [WebAPIs] Copy to clipboard 複製到剪貼簿

範例程式碼:當瀏覽器不支援時讓按鈕變成複製功能

這裡提供實際的範例可以作為參考:
// 選擇和 DOM 有關的元素
const btn = document.querySelector('button');
const result = document.querySelector('.result');

// 當使用者點擊分享時要帶入的資訊
const shareData = {
  url: 'https://pjchender.blogspot.com', // 要分享的 URL
  title: 'PJCHENder 那些沒告訴你的小細節', // 要分享的標題
  text: '好多眉眉角角啊', // 要分享的文字內容
};

btn.addEventListener('click', () => {
  // 判斷瀏覽器是否支援 Web Share API
  if (navigator.share) {
    handleNavigatorShare();
  } else {
    handleNotSupportNavigatorShare();
  }
});

// 當瀏覽器支援 Web Share API 時
async function handleNavigatorShare() {
  try {
    await navigator.share(shareData);
    result.textContent = '感謝你的的分享';
  } catch (err) {
    // 使用者拒絕分享或發生錯誤
    const { name } = err;
    if (name === 'AbortError') {
      result.textContent = '您已取消分享此訊息';
    } else {
      result.textContent = err;
      console.log('發生錯誤', err);
    }
  }
}

// 當瀏覽器不支援 Web Share API 時,點下去變成複製
function handleNotSupportNavigatorShare() {
  const contentToCopy = document.querySelector('#content-to-copy');
  contentToCopy.value = shareData.url;
  contentToCopy.setAttribute('type', 'text'); // 不是 hidden 才能複製
  contentToCopy.select();

  try {
    const successful = document.execCommand('copy');
    const msg = successful ? '成功' : '失敗';
    alert(`${shareData.url} - 複製${msg}`);
  } catch (err) {
    alert('Oops, unable to copy');
  }

  /* unselect the range */
  contentToCopy.setAttribute('type', 'hidden');
  window.getSelection().removeAllRanges();
}

參考文章

2019年11月16日

[Samsung] 沒辦法看訊息通知?讓 Bixby Routines 朗讀通知給你聽

平常在開車或是工作時,並不是非常方便看手機,這種時候若收到 Line 或者簡訊通知時,常常都只聽得到通知卻不知道也不方便點開來看內容,這時候就會很希望手機的語音助理能夠把通知直接念出來讓我知道,至少可以知道是不是有急著需要處理的事情。
其實這個功能已經內建在三星這個看似毫無作用的 Bixby Routine 中了,這篇文章中就來看看可以怎麼樣使用。如果懶得看文字的話可以直接參考這個影片:

進入 Bixby Routine

要進入 Bixby Routine 可以從「設定」-->「進階功能」-->「Bixby Routines」中找到:
Bixby 朗讀通知功能
接著點擊上方的新增,可以為這個 routine 取個名稱,例如這裡我叫「唸給我聽」:
Bixby 朗讀通知功能
接著就可以設定「如果⋯則⋯」,這裡我先設定手動啟動(即,已輕觸開始按鈕),平常我也會設成一旦連接到藍芽耳機就啟動:
Bixby 朗讀通知功能
按下完成儲存後,像是這種需要手動開啟的 routine,會詢問你要不要新增到桌面上,點選是支後桌面上就會多了啟動和關閉這個 Routine 的按鈕:
Bixby 朗讀通知功能

當你希望手機擁有朗讀通知的功能時,例如開車、工作時,只要點選這個按鈕,一旦有收到推播通知,手機就會念出來給你聽。

Bixby Routines 的更多功能

這裡雖然是透過 Bixby Routines 來達到朗讀通知的功能,但實際上 Bixby Routines 可以做到更多的功能,它可以設定「當你到公司時則⋯」、「當你回家時則⋯」,可以是開啟 WIFI、開啟某個應用程式等等,功能還蠻多樣的話,善用它的話覺得會是個相當方便好用的功能。
若還不清楚怎麼操作的話,一樣可以回頭參考示範影片:

2019年9月3日

[Mac] 如何透過 iMovie 輸出高畫質影片(4k, 1080p)

iMovie 的專案會依據「第一部」匯入到時間軸中的媒體,以此決定這個影片最後可以輸出成多高的解析度,因此若你最後想輸出成 4K 的影片,只需要:
  1. 先到網路上下載一部 4k 的影片(參考影片下載連結
  2. 新增一個全新的專案(專案一定要是全新的,因為是以第一個匯入時間軸的媒體來決定最後輸出的解析度)
  3. 將 4k 影片匯入媒體後,拖曳到時間軸內,成功的話,在右邊齒輪(設定)的地方點一下,會看到解析度出現 4k 選項:
iMovie
  1. 接著,如果原本已經有編輯好的內容,可以複製貼在時間軸後面
  2. 把第一個放入時間軸的 4k 影片移除
  3. 選擇匯出成 4k 影片:
iMovie
專案一定要是全新的,因為是以第一個匯入時間軸的媒體來決定最後輸出的解析度

示範操作影片

參考資料

2019年8月31日

[多圖] 三星 Samsung S10+ Plus 與 Note 10 選擇困難?相機拍照、螢幕與效能比較心得

keywords: samsung, camera, s10+, s10plus, note10, performance, screen
imgur
最近剛好有機會同時入手三星(Samsung)的 S10+ Plus 和 Note 10(不是 Note 10+),可以分享一下這兩隻使用上的心得。
直接說結論:相較於 Note10,S10+ 的螢幕真的無可挑惕,色彩的呈現和解析度都非常棒;而 Note10 則是在 App 的安裝速度上有較明顯的提升。兩隻在主鏡頭的拍攝略有差異,主要體現在 Note 10 的成像有更明顯的對比,因此天空會更藍一些,較為吸睛,但有時對比太重會有色偏或修圖感較重的情況(覺得和這幾年 iPhone 成像對比也變強有些相似);S10+ 則中規中矩,在顏色的呈現上和原本的色彩比較接近。
台灣上市的 S10+ CPU 使用的是三星自家的 exynos 9820;Note 10 則是使用 高通 Qualcomm 855

螢幕(screen)

以前對於螢幕都沒有特別的感覺(不論是小米、三星、LG、HTC),至少不會讓我馬上感覺到「怪怪的」,但這次用了 Note10 之後,第一次感覺到螢幕真的有差異(差異的大小每個人感受不同),特別是和 S10+ 相比,可能眼睛有點被 S10+ 的螢幕給慣壞了。
這兩隻螢幕在色溫上的差異蠻明顯的。打開白屏的情況下就可以很明顯看得出來。將同一張照片放到這兩隻手機上時,可以看到很明顯的顯色不同。這也導致有時候在 Note 10 上看的相片在拿到 S10+ 或上傳到 MAC 後卻又是另一種感覺,也就是說同一張照片在手機上和電腦上色彩看起來會不太一樣
若想看螢幕的色溫差異可以參考 ptt 的這篇文章:[問題] 請問Note10+螢幕是預設偏黃嗎
對我個人來說 Note10 上的白色會給我沒那麼乾淨的感覺,並有些許偏黃,然後成像解析度也沒那麼清晰的感覺,和之前同樣是 1080p 的手機相比,之前的手機反倒不會給我這種感覺。
有網友表示可以在顯示的地方,把「背景效果」調成「鮮豔」,並到「進階設定」的地方將綠色拉到底,紅色降兩格會比較接近原本的白色,有需要的朋友可以試試看:
s10+ vs note10
因為每個人的感受和每台手機差異可能不同,建議如果在意的人可以到現場看實機感受一下
不論 Note 10 或 Note 10+ 似乎都有人反映這樣的情況,但每個人感受和每台手機的差異不同,可以看在 Mobile 01, pttfb 社團內都有不止一篇以上的討論
Note10 在螢幕的表現上偏黃,但因為每個人的感受和每台手機差異可能不同,如果在意的人可以到現場看實機感受一下。

效能(performance)

不看任何跑分軟體或數字的話,從主觀使用感受上對我來說沒有什麼差異,日常使用都不會有什麼卡頓的情況,遊戲順暢度給我的感覺也差不多
硬要比較的話,下載並安裝同一款 App 時 Note 10 花費的時間比較少,且在玩遊戲時 Note10 會再更流暢一些;但當我在用影片編輯軟體操作時,S10 + 的輸出速度則明顯較快。
簡單的說,我覺得高通在多工任務時處理得比較好,因此在 App 的切換上或同時運作多個 App 時比較流暢;而獵戶座在單槍匹馬的執行上速度更快,讓他不要分心乖乖一次做一件事他會做得更好。發熱程度的話,兩者在玩遊戲時都會有明顯發熱的感受。
日常使用都不會有什麼卡頓的情況,遊戲順暢度給我的感覺也差不多

相機拍照(camera)

主鏡頭

雖然 S10+ 和 Note 10 用的是相近相機模組,但兩者成像上仍有所差異,但我覺得沒有孰優孰劣,端看自己喜歡怎麼樣的風格
這兩隻手機拍出來的照片可以用成像的對比度簡單地區分出來。相較於以往三星手機飽和度相對較高的情況來說,這次 Note 10 的相片則是對比度較高,具體來說,會使得天空更藍一些、文字則會有加粗的效果,整體來說相片是更吸睛的,但有些時候對比度過高時會有色偏的情況,原本的紅色變得更深,或者是給人較強的修圖感。
S10+ 的相片則比較中規中矩,相較之下顏色比較準確,白色和文字的呈現上會比較乾淨一些,但也使得直接輸出的相片和 Note 10 相比沒那麼吸睛。
從下面這一系列的照片中可以蠻清楚看到上面的結論,可以先看一下你比較喜歡哪一邊的色彩,最後會在公布左邊和右邊各式哪台手機所拍:
s10+ vs note10
s10+ vs note10
s10+ vs note10
s10+ vs note10
s10+ vs note10
s10+ vs note10
s10+ vs note10
s10+ vs note10
s10+ vs note10
s10+ vs note10
s10+ vs note10
s10+ vs note10
s10+ vs note10
s10+ vs note10
s10+ vs note10
s10+ vs note10
s10+ vs note10
s10+ vs note10
s10+ vs note10
s10+ vs note10
s10+ vs note10
答案揭曉,左邊的照片都是使用 S10+ 所拍攝,右邊的照片則是使用 Note 10 進行拍攝,不知道你比較喜歡哪一個呢?
若想要看完整的圖片可以到此 Google 相簿
兩者用的雖然是相似的鏡頭模組,但成像上仍有所差異,S10 + 中規中矩、顏色較準確;Note 10 對比度高、照片較吸睛、但有時修圖感較強。我覺得沒有孰優孰劣,端看自己喜歡怎麼樣的風格。

前鏡頭(自拍鏡頭)

在前鏡頭方面 S10+ 和 Note 10 的成像方式可以說和主鏡頭是完全反過來。
S10+ 對比較強烈,在光線充足的情況下色彩較豐富,但有時會對比拉得太高,讓相片本身很不自然,這種情況在開啟廣角時更佳明顯。Note 10 在顏色上則比較自然舒服些,但相對的色彩表現上比較沒那麼豐富。完全取決於個人喜好和感受。
這裡避免傷眼就不附上自拍的照片,有興趣可以再去 Youtube 找相關的影片。

延伸閱讀