[Day 10] 讓 C# 也可以很 Social — .NET 6 C# 與 Line Services API 開發 — Imagemap message 介紹 & 實作

APPX
appxtech

--

Hello 各位好,本篇要介紹的是 Imagemap message,從 Imagemap 開始,後面要介紹的訊息與前面幾個相比都複雜非常多,會盡量將各個面向都介紹到的,馬上開始!

<<回顧上一篇<<

本篇大綱

前言、
Imagemap 介紹
一、
Imagemap 文件屬性介紹
二、
根據文件內容宣告 Class
三、
製作 Imagemap 圖片傳輸機制
四、
結語/腦筋急轉彎/範例程式碼

前言、Imagemap 介紹

Imagemap 是一個以圖片為基礎,可以在圖片上面設定多個可點擊區域並且指定點擊時產生事件的訊息,而一張圖片最多可以設置 50 個可點擊區域

另外,Imagemap 也可以在圖片上嵌入一個影片,並放置一個超連結給這部影片。

實例

首先給各位看幾個 Imagemap 的實際應用~

①星巴克

星巴克將 Imagemap 用作選單,使用透明背景提高圖片泛用性。

②路易莎

路易莎將 Imagemap 用作活動行銷,圖片上方說明活動內容,下方提供訂餐與分享按鈕來提高活動的觸及率。

③CoCo

CoCo 使用 Imagemap 製作了一系列的心理測驗與飲料推薦遊戲,提高使用者與其LineBot互動的趣味性。

從這幾個例子可以得知 Imagemap 的用途非常廣泛。

接下來正式開始實作 Imagemap🔗 文件連結

一、Imagemap 文件屬性介紹

屬性介紹

  • BaseUrl : Imagemap 圖片的 htpps 路徑,這裡要帶的內容並不是圖片檔的絕對路徑,而是帶到存放圖片的資料夾即可,原因後面提到 Imagemap 機制時會說明。
  • AltText : 在聊天列表看到的文字內容。
  • BaseSize : 指明寬度 1040px 的圖片相對應高度為多少 px。
  • Video : 若需要內嵌影片時才需要宣告此屬性:

①OriginalContentUrl : 影片檔 https 絕對路徑

②PreviewImageUrl : 影片預覽圖片 https 絕對路徑

③Area : 由 XY 為起點,向右、向下根據 Width&Height 畫出長方形。

④ExternalLink : 影片播完後會多出一個顯示 Label 設定文字的按鈕,按下即可跳轉至設定的 uri。

1. Imagemap Action

在 Imagemap 上可使用的 action 有以下兩個

  • Message Action
    此動作執行後,使用者會傳送 Text 屬性帶入的文字給 Line Bot
  • URI Aciton
    此動作執行後,會開啟 LinkUri 屬性帶入的網址

值得一提的是,Line 有提供一系列的 url schema,使得 uri action 也能夠做到許多動作,也就是這個功能使 Imagemap 完全不輸之後要介紹的幾種訊息

2. Imagemap Area

Area 是用來定義區域範圍的 Class,根據坐標 XY 為左上角的起點,向右畫出 Width 長度,向下畫出 Height 長度的長方形範圍。

二、根據文件內容宣告 Class

  • 在 Dtos 資料夾中新增 Actions 資料夾,並在 Actions 資料夾中新增 ImagemapActionDto.cs
namespace LineBotMessage.Dtos
{
public class ImagemapActionDto
{
public string Type { get; set; }
public string? Label { get; set; }

// Message action
public string? Text { get; set; }

// Uri action
public string? LinkUri { get; set; }

public ImagemapAreaDto Area { get; set; }
}
}
  • 在 Dtos/Messages 資料夾中新增 ImagemapMessageDto.cs
using LineBotMessage.Enum;
namespace LineBotMessage.Dtos
{
public class ImagemapMessageDto : BaseMessageDto
{
public ImagemapMessageDto()
{
Type = MessageTypeEnum.Imagemap;
}

public string BaseUrl { get; set; }
public string AltText { get; set; }
public ImagemapBaseSizeDto BaseSize { get; set; }
public ImagemapVideoDto? Video { get; set; }

public List<ImagemapActionDto> Actions { get; set; }
}

public class ImagemapBaseSizeDto
{
public int Width { get; set; }
public int Height { get; set; }
}

public class ImagemapVideoDto
{
public string OriginalContentUrl { get; set; }
public string PreviewImageUrl { get; set; }
public ImagemapAreaDto Area { get; set; }
public ImagemapVideoExternalLinkDto ExternalLink { get; set; }
}

public class ImagemapAreaDto
{
public int X { get; set; }
public int Y { get; set; }
public int Width { get; set; }
public int Height { get; set; }
}

public class ImagemapVideoExternalLinkDto
{
public string LinkUri { get; set; }
public string Label { get; set; }
}
}
  • 在 LineBotService 中的 BroadcastMessageHandler Function 添加對應的 case
case MessageTypeEnum.Imagemap:
messageRequest = _jsonProvider.Deserialize<BroadcastMessageRequestDto<ImagemapMessageDto>>(strBody);
break;

三、製作 Imagemap 圖片傳輸機制

Imagemap 機制說明

根據文件內容,一個 Imagemap 的圖片需要準備5種不同寬度的尺寸,分別是 240px、300px、460px、700px、1040px,並且是 JPEG 或 PNG 格式,並且將5張圖片放入同一個資料夾後將副檔名刪除,最後傳送 Imagemap 訊息時的 BaseUrl 帶到存放圖片的資料夾名稱即可,Line 會依據使用者裝置的大小選擇要載入哪種寬度的圖片,並將這個 Request 送給我們的伺服器。

例如 : (5張圖片放在 UploadFiles/ImagemapImages/DemoImage 中)

  • Imagemap 的 BaseUrl 屬性要這樣帶 :
    {ngrok host 位置}/UploadFiles/ImagemapImamges/DemoImage
  • Line 會依據使用者的裝置帶入寬度並送出 Get Request
    {ngrok host 位置}/UploadFiles/ImagemapImamges/DemoImage/700

— — — 以上是官方提供的方法 — — —

不過,因為 .NET 機制的關係,不容易實現這種機制,並且想要有個通道控制其圖片的傳輸,所以我這邊決定另外實作一個 Controller 去負責這個圖片的 Request

1. 圖片準備

  • 在 UploadFiles 中新增 ImagemapImages 資料夾
  • 再新增一個 DemoImage 資料夾放入準備好的 5 種寬度的圖片(不用刪除副檔名) 範本圖片連結

2. Controller 實作

在 Controllers 資料夾新增 FileController.cs

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.StaticFiles;

namespace LineBotMessage.Controllers
{
[Route("api/[Controller]")]
[ApiController]
public class FileController : ControllerBase
{

private readonly IConfiguration _configuration;
public FileController(IConfiguration configuration)
{
_configuration = configuration;
}

/// <summary>
/// Only for Imagemap message 讀取圖片
/// </summary>
/// <param name="folderName"></param>
/// <param name="imageSize"></param>
/// <returns></returns>
[HttpGet("UploadFiles/ImagemapImages/{folderName}/{imageSize}")]
public IActionResult GetImagemapImage(string folderName, string imageSize)
{
//FileStream fs = new FileStream();
var path = $"{_configuration.GetValue<string>(WebHostDefaults.ContentRootKey)}/UploadFiles/ImagemapImages/{folderName}/{imageSize}.png";
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
{
var fileBytes = System.IO.File.ReadAllBytes(path);
new FileExtensionContentTypeProvider().TryGetContentType(Path.GetFileName(path), out var contentType);
return new FileContentResult(fileBytes, contentType ?? "application/octet-stream");
}
}
}
}

3. 測試

  • 使用 Swagger 廣播測試
  • 沒有嵌入影片的 Imagemap Json Body
{
"Messages": [
{
"Type": "imagemap",
"BaseUrl": "{ngrok 位置}/api/File/UploadFiles/ImagemapImages/DemoImage",
"AltText": "This is an imagemap",
"BaseSize": {
"width": 1040,
"Height": 1040
},
"Actions": [
{
"Type": "message",
"Text": "查看商品1",
"Area": {
"X": 0,
"Y": 0,
"Width": 520,
"Height": 520
}
},
{
"Type": "uri",
"LinkUri": "https://www.appx.com.tw/newcourse",
"Area": {
"X": 520,
"Y": 0,
"Width": 520,
"Height": 520
}
},
{
"Type": "uri",
"LinkUri": "https://www.appx.com.tw/lecture",
"Area": {
"X": 0,
"Y": 520,
"Width": 520,
"Height": 520
}
},
{
"Type": "message",
"Text": "查看商品4",
"Area": {
"X": 520,
"Y": 520,
"Width": 520,
"Height": 520
}
}
]
}
]
}
  • 廣播結果,各位自行測試點擊效果是否跟傳送的 Json 設定一樣。
  • 嵌入影片的 Imagemap 會將影片蓋到圖片上方,我這邊將影片位置放在上半部商品1、2的範圍。
{
"Messages": [
{
"Type": "imagemap",
"BaseUrl": "{ngrok 位置}/File/UploadFiles/ImagemapImages/DemoImage",
"AltText": "This is an imagemap",
"BaseSize": {
"width": 1040,
"Height": 1040
},
"Video": {
"OriginalContentUrl": "{ngrok 位置}/UploadFiles/video1.mp4",
"PreviewImageUrl": "{ngrok 位置}/UploadFiles/appx.png",
"Area": {
"X": 0,
"Y": 0,
"Width": 1040,
"Height": 520
},
"ExternalLink": {
"LinkUri": "https://www.appx.com.tw",
"Label": "See More"
}
},
"Actions": [
{
"Type": "uri",
"LinkUri": "https://www.appx.com.tw",
"Area": {
"X": 0,
"Y": 520,
"Width": 520,
"Height": 520
}
},
{
"Type": "message",
"Text": "Hello",
"Area": {
"X": 520,
"Y": 520,
"Width": 520,
"Height": 520
}
}
]
}
]
}
  • 廣播結果

四、結語

Imagemap 介紹就到這邊結束了,如果照著訊息順序介紹下去的話下一篇應該要介紹的是 template message,不過既然這篇已經使用到了 message action 和 uri action,那下一篇就把 line actions 補上,正好 template 也會用到 line action 的功能,所以在介紹 template message 之前先插入 line actions 介紹~下一篇見。

腦筋急轉彎

  • 若要照著 Line 官方的方式提供圖片,伺服器該具備什麼機制?我們程式該做哪些調整呢?

範例程式碼

如果想要參考今天範例程式碼的部份,下面是 Git Repo 連結,方便大家參考。

Day10_Imagemap Message

>>下一篇>>

--

--