資安

可摺疊Web可能會給我們帶來的變化

作者 | 大漠

image.png
可摺疊Web的說法是可摺疊設備帶來的。可摺疊設備形式多樣,從筆記本電腦到手機,再到新奇的雙屏幕混合設備。對於這類新發明並沒有一個全面的定義,但大多數都可以歸為兩類。“可摺疊”是指屏幕可以摺疊的設備(比如華為Mate X,三星Galaxy Z Flip);而“雙屏”設備的屏幕是分開的,但也可以以獨特的方式一起工作,以靈活的形式提供生產力(比如,微軟的Surface Neo和Surface Duo)。當涉及到Web設計時,這兩種類型可能會遵循類似的規則。如果這項技術能大獲成功,那麼Web設計將面臨十年來最大的變革。這對於我們Web開發者而言,也將會開啟新的旅程。

聽起來就很令人興奮,但這到底意味著什麼呢?可摺疊Web將帶來新的挑戰,新的機遇,而且很可能還會帶來新的概念。互聯網可能也會經歷自智能手機以來最大的變革。你可能會認為這是一種炒作,但事實上這樣的一天已經離我們不是太遠。記得在去年這個時候,有些移動品牌商,比如華為,三星都推出可摺疊的硬件設備,而微軟,蘋果等公司在幕後的努力也不遜色。可以說可摺疊Web即將到來。我們真的應該去思考可摺疊Web可能會給我帶來什麼變化?如果這一天真的到來,我們的技術是否能支持該設備。簡單地說,我們開發的Web頁面能不能在可摺疊設備和雙屏幕上完美的運行。

可摺疊和雙屏設備

可摺疊設備採用的是一種柔性屏幕技術,該技術的研究始於20世紀70年代,但直到世紀之交才得到真正的發展。特別是在去年,得到了爆發式的發展——在市場上能看到一些可摺疊設備終端。比如三星Galaxy Z Flip手機,模仿的是老式的翻蓋手機:
image.png
比如三星的Galaxy Fold手機,在摺疊狀態是一個小屏幕,展開狀態是一個寬屏幕:
640.gif
比如華為Mate X,屏幕是包裹在手機外面的:
640 (1).gif
還有很多像電子書一樣,當設備完全打開時,內部的兩個顯示屏會合二為一。通常在外面有一個獨立的小屏幕,這樣用戶在使用的時候就不用打開它。

雙屏幕設備是具有兩個對稱屏幕的便攜式設備,以獨特的方式一起工作,以靈活的形式提供生產力。比如像微軟的Surface Neo和Surface Duo這樣的雙屏幕設備,人們可以比以往任何時間都更快地完成工作。如果你使用過Surface Neo這樣的雙屏幕設備,你可以在一個屏幕上做筆記,在傳輸過程中在另一個屏幕上查看完整的項目建議書:
image.png
儘管現在市場上有不同的摺疊屏,雙屏幕設備,而且還會有更多的類似設備出現,但我們相信為這些設備設計應用程序會有一個共同的方法。我們希望這將幫助你的應用程序能跑在更多的設備上,而不需要為不同的設備做特殊的設計和處理。

換句話說,在可摺疊屏或雙屏幕的設備上,用戶可以做更多的事情,比如說讓屏幕分屏,可以同時打開多個應用程序:
image.png
也可以打開同一個應用,在應用中分屏,打開不同的頁面,比如:
640 (2).gif
像上圖這樣,應用程序在兩個屏幕上顯示,就是所謂的跨屏佈局。默認情況下,該應用程序將表現得好像它是在一個更大的屏幕上顯示。你也可以改變你現有的應用程序佈局來適應兩個屏幕之間的縫隙,或者你可以更進一步,允分的利用雙屏幕設備而專門創建不同的佈局控件。比如iPad版本的手淘,就可以分屏展示:
image.png

新的 Web 標準、新的體驗和新的問題

可摺疊和雙屏幕設備正在出現。這已經不是概念,也不是炒作。這更不是重點。重點是:

可摺疊和雙屏幕這項技術將如何影響Web開發人員、用戶體驗設計師以及其他以提供高質量瀏覽體驗為業務的人。

首先可摺疊和雙屏幕會給視覺設計師在做設計的時候帶來很大的變化。

整個可摺疊的概念是基於你可以把你的手機變成平板電腦的想法。市場上大多數平板電腦的屏幕寬高比都是 4:3,所以手機和平板電腦的混合也應該是4:3。這使用摺疊設備達到3:2。而這些比率都不能保證16:9或18:9的真實視頻體驗。其中4:3的寬高比更適合在各種文本和圖形編輯器中執行任務和工作,比如iPad,但它需要更大的分辨率,這是可摺疊設備無法做到的。這使得大多數可摺疊手機處於一個模糊地帶,給人用戶的體驗就會變得很糟糕,這也是因為在傳統手機中是無法達到16:9的比例。

為了讓可摺疊手機成為一種有用的媒體設備,它必須轉換成16:9或18:9的設備,然後再摺疊成8:9或9:9 —— 基本上就是一個正方形。@Nathan Cunn通過計算得出結論,摺疊手機的完美寬高比應該是其寬度的1.4倍。
image.png
這也將會是iPhone摺疊屏將會採用的一種寬高比例:
image.png
除此之外,不管是可摺疊設備還是雙屏幕設備,最大的特徵就是屏幕變大了,在展開的狀態下和平板一樣了。這樣一來,可用的空間就變大了。

可摺疊和多屏設備打破了移動設備(手機)可用空間小的束縛!

空間大了,能放置的內容就多了,如果設計還是按著以前的思路,直接拉伸平滿全屏,就過於浪費了。面對這樣的場景,除了響應式Web設計能幫助我們更好的利用可用空間之外,還可以參照淘寶設計提出的一個概念:

讓你的內容像水一樣的流動(“Content is like water”)

用一張圖來描述:
image.png
有關於這方面更詳細的介紹,可以關注淘寶設計微信公眾號。

你可以搜索“可摺疊”關鍵詞,能找到一些這方面的文章,比如:

對於雙屏幕給設計帶來的變化,或者說設計應該要注意的細節,可以閱讀微軟官方有關於雙屏幕的介紹:《Introduction to dual-screen devices》

另外,摺疊屏幕還會帶來一些其他的設計和體驗變化。

單(雙)手移動設計

隨著狀態的改變(這裡的狀態是摺疊和展開狀態,單屏和多屏狀態),整個體驗本身也隨之改變。目前大多數用戶都習慣用一隻手操作移動設備(手機),而展開狀態,就像iPad了,這個時候需要兩隻手來操作設備(或應用)。
image.png

手機操作 vs 平板操作

屏幕連續性和間隔

可摺疊設備和多屏幕設備有著明顯的區別。

可摺疊設備在展開狀態時,它的屏幕是連續性的,我們在設計的體驗應該無縫地轉移到全屏上。
640 (3).gif
針對這樣的情景,如果只是粗暴的放大到全屏,那麼佈局上不會有太多的變化,只不過對於Web中的部分對象會變得模糊,比如圖像。當然,也可以考慮設計上做差異性的處理,比如說做分屏設計:
640 (4).gif
對於多屏幕設備,有可能屏幕不是連續性的,比如微軟的Surface Neo和Surface Duo,屏幕之間就有一個間隙:
image.png
在設計和佈局的時候,就需要避免Web對象處在兩個屏幕的間隙之間,比如:
image.png
或者:
image.png

多窗口,多應用

前面提到過,摺疊屏和多屏幕最大的特徵之一,就讓我們有更多的空間可利用。這樣對於用戶來說,對於處理多任務更友好,能同時做更多的事情。因此,我們應該始終考慮用戶可能會同時運行多個App應用。比如說,一邊查看日曆,一邊查看地圖,一邊看新聞:
image.png

除了同時打開多個App應用之外,還可以在同一個App中,分屏做不同的事情,比如,一邊看直播,一邊逛淘寶:
640 (5).gif
摺疊屏和多屏幕除了給設計師帶來新的挑戰之外,給Web開發者也帶來相應的挑戰。在去年華為Mate X出來的時候,有幸參與在Mate X做一些Web端的適配處理。主要處理H5的應用完美適配摺疊屏設備。

由於相關H5業務採用的都是視窗單位vw(我常稱該方案為vw-layout),能較好的讓相應的H5業務適配摺疊屏展開狀態,但也存在一些相應的問題,最為突出的是圖像變得模糊:
image.png
當然也嘗試著採用響應式Web設計來做不同的佈局處理:
image.png
雖然該方式可以讓我們的H5應用最大化的利用摺疊屏可用空間,但也存在一定的缺陷。因此在《聊聊安卓摺疊屏給交互設計和開發帶來的變化》一文中提出相應的概念:

處理摺疊屏時,我們應該像一些帶有劉海設備(比如iPhone X)一樣,具有獨特的檢測特性來檢測摺疊設備或多屏幕設備。

值得慶幸的是這一年來,在這方面有了明顯的變化,尤其是微軟公司的團隊對可摺疊技術的探究和討論非常的積極。在今年2月份,三位微軟開發人員@Bogdan Brinza@Daniel Libby@Zouhir Chahoud發表了一篇文章,解釋如何使用JavaScript API和CSS 媒體查詢來處理可摺疊和多屏幕設備的佈局

該文檔提出兩個概念:用於雙屏幕布局的CSS 和 窗口段枚舉的JavaScript API。它的宗旨是作為討論摺疊屏和多屏幕在Web開發中技術標準。即:以可摺疊和雙屏幕設備為目標的Web開發人員能夠在跨多個顯示區域的窗口中有效的對Web應用進行佈局。

未來處理可摺疊或多屏幕的 Web 技術

@Bogdan Brinza@Daniel Libby@Zouhir Chahoud三位開發者在Github上發表的文檔《Web Platform Primitives for Enlightened Experiences on Foldable Devices》來看。處理可摺疊和多屏幕設備的Web佈局主要由兩部分特性組成,其一是CSS的媒體查詢特性,其二是JavaScript API。

接下來,我們主要圍繞著這兩個部分來展開。

用於構建雙屏幕布局的 CSS 特性

特別聲明:用於雙屏幕布局的CSS還處於W3C規範的草案當中,一切皆有可能會變。

@Brinza、@Libby和@Chahoud提出了一個CSS特性,即媒體特性,它可以確定網站是否跨越兩個相鄰的顯示區域,以及這兩個相鄰顯示區域的配置。相應的還提出了另一個特性,即環境變量(指的是用戶代理定義的環境變量),它將幫助Web開發人員以CSS像素計算每個屏幕區域的大小。

為什麼要提出新的CSS特性

當瀏覽器窗口跨越設備摺疊時,告訴Web開發者摺疊方向和顯示邊界可以幫助他們開發出來具有較好體驗的Web應用。這裡快速概述可能會出現的模式。

將更大屏幕的UI模式帶到更小的便攜設備

由於屏幕尺寸的限制,傳統的便攜式觸摸設備在很大程度上依賴於“疊加視圖”,比如點擊收件箱列表中的一封郵件,就會導致整個收件箱列表視圖被選中的郵件內容視圖所取代。這種行為通常會創建額外的操作步驟;而在更大屏幕的設備上將會有一個更自然的配置,郵件收件箱列表視圖和郵件內容視圖是並排的。
image.png
當然,這種重新創造的模式並不是唯一的解決方案,只不過可摺疊屏和多屏幕設備相對於傳統的便攜觸摸式移動設備來說多了一個顯示器,相當於增加一個屏幕空間,這樣一來可以為Web開發者和設計師提供獨特的機會來創造新的體驗。
image.png

輕鬆改進現有的Web應用和UI組件

Web開發人員可能不想為這類設備引入主要的UI更改,而只想簡單地移動一些組件。在下面的示例中,對於模態對話框(Modal)避免設備摺疊更有意義(無論可摺疊設備是無縫的還是有間隙的),並允許Web開發人員逐步增強他們的站點,提供更好的體驗。
image.png
也正因為這些原因,提出了相應的CSS特性和設計原則。

CSS媒體特性:spanning

提出一個新的媒體特性:spanning,該特性可用於檢測瀏覽器窗口是否跨越多個顯示區域。
image.png
spanning特性主要有三個值:

  • single-fold-vertical:屏幕是水平的,佈局視圖跨越單個摺疊(兩個屏幕)並且摺疊姿勢是垂直時(分左右兩邊),這個值是匹配的
  • single-fold-horizontal:屏幕是垂直的,佈局視圖跨越單個摺疊(兩個屏幕)並且摺疊姿勢是水平時(分上下),這個值是匹配的
  • none:描述瀏覽器窗口不處於跨越模式時的狀態

識別摺疊或多屏設備的CSS環境變量

這個有點類似於劉海設備一樣,通過env()函數來識別環境變量,即識別安全區域:

  • env(safe-area-inset-top):在Viewport頂部的安全區域內設置量(CSS像素)
  • env(safe-area-inset-bottom):在Viewport底部的安全區域內設置量(CSS像素)
  • env(safe-area-inset-left):在Viewport左邊的安全區域內設置量(CSS像素)
  • env(safe-area-inset-right):在Viewport右邊的安全區域內設置量(CSS像素)

image.png
這份建議預定義了幾個可識別摺疊或多屏設備的CSS環境變量:fold-top、fold-left、fold-width和fold-height。
image.png
Web開發人員可以利用這些變量來計算橫屏和豎屏的每個屏幕片段大小。

注意,這些CSS環境變量的值是CSS像素,並且是相對於佈局視圖的(即在客戶端座標中,由CSSOM視圖定義)。當不處於跨越狀態時,這些值將被視為不存在,則會取env()函數的回退值。

來看一個簡單的示例:一個地圖應用程序,在一個屏幕上顯示地圖,在另一個屏幕上顯示搜索結果。如下圖所示:
image.png
如果用CSS代碼來實現的話,大致如下:


@media (spanning: single-fold-vertical) {   
    body {
        flex-direction: row;
    }

    .map {
        flex: 1 1 env(fold-left)
    }

    .locations-list {
        flex: 1;
    }
}

spanning 的 Polyfill

到目前為止,新增的CSS媒體特性spanning和相應的環境變量都還處於草案的討論階,但如果你要嘗試著在摺疊設備或多屏幕設備上使用該特性的話,可以使用@darktears 提供的一個Polyfill

這個Polyfill的使用很簡單,你可以使用NPM將這個Polyfill加載到你的項目中:

npm install --save spanning-css-polyfill

安裝完之後,通過<script>將對應的spanning-css-polyfill.js引入到項目中:

<script type="module" src="/path/to/modules/spanning-css-polyfill.js"></script>

也可以使用import的方式引入:

import "/path/to/modules/spanning-css-polyfill/spanning-css-polyfill.js";

這樣你就可以在CSS中使用spanning這個新媒體查詢特性和CSS環境變量fold-top、fold-left、fold-width和fold-height。

當然,你還可以手動改變顯示(display)相關的配置。比如,通過導入FoldablesFeature對象:

import { FoldablesFeature } from '/path/to/modules/spanning-css-polyfill/spanning-css-polyfill.js';

可以通過FoldablesFeature對象來更新像spanning、foldSize和browserShellSize等值。你也可以訂閱change事件,以便spanning媒體查詢特性或環境變量發生變更時得到相應的通知。

import { FoldablesFeature } from '/path/to/modules/spanning-css-polyfill/spanning-css-polyfill.js';

const foldablesFeat = new FoldablesFeature;

// Add an event listener.
foldablesFeat.onchange = () => console.log("change");

// Add as many event listeners as you want.
foldablesFeat.addEventListener('change', () => console.log("change"));

// Change a single value; results in one update (one 'change' event firing).
foldablesFeat.foldSize = 20;

// Change multiple values by assignment; results in one update.
Object.assign(foldablesFeat, { foldSize: 50, spanning: "none"});

// Change multiple values in one scope; results in one update
(function() { foldablesFeat.foldSize = 100; foldablesFeat = "single-fold-horizontal" })();

有關於spanning更詳細的使用,可以查看Github上的相關教程

枚舉窗口片段的 JavaScript API

特別聲明,枚舉窗口片段的JavaScript API已移到W3C第二屏幕社區組。相關的解釋、問題和評論,可以參閱GitHub的webscreens/window-segments倉庫。

這裡提出了一個窗口片段的新概念,它表示位於單獨(相鄰)顯示上的窗口區域(及其尺寸)。窗口片段尺寸以CSS像素表示,並允許Web開發者通過JavaScript API對窗口片段進行枚舉,在相應的窗口片段上放置獨立內容。

這個建議主要針對響應式場景,在這種情況下,Web應用程序希望利用跨越多個顯示的優勢,通過用戶、窗口管理器將其置於該狀態。它不適合將內容預先放置在各種可用顯示的單獨頂級瀏覽器上下文的情況(這屬於Window Placement APIPresentation API)。請注意,使用枚舉窗口片段的API和Web現有的特性,可以使用JavaScript來編寫交叉顯示和窗口的矩形,同時考慮devicePixelRatio來,計算橫跨多個顯示的窗口區域。不過,這個並不能正確的處理未來設備形式中存在的極端情況,因此,這個提議試圖解決Web開發人員針對或考慮顯示內容屏幕作為一個實際的起點。

簡單地來說,Web開發者可以使用getWindowSegments()來獲取一個DOMRects數組,然後根據每個窗口片段返回的數據,開發人員能夠推斷出可用鏈接(Hinge)的數量以及其方向。

用戶可以在任何時候將瀏覽器窗口脫離跨越模式,並將其放在某個屏幕上,反之亦然,在這種情況下,將觸發窗口resize事件,從而可以查詢並獲得可用屏幕段的數量。

比如我們上面提到的示例:
image.png
如果使用JavaScript來解決的話,可以像下面這樣:

const screenSegments = window.getWindowSegments();

if( screenSegments.length > 1 ) {
    // 現在我們知道這個設備是可摺疊(可多屏幕)的
    // 建議測試 screenSegments[0].width === screenSegments[1].width 
    // 可以更新CSS類,實現不同的佈局效果

    document.body.classList.add('is-foldable');
    document.querySelector('.map').classList.add('flex-one-half');
    document.querySelector('.locations-list').classList.add('flex-one-half');
}

我們再來看另一個示例,當窗口的resize事件和spanning狀態發現變化時處理方案。
image.png
先看CSS的解決方案:

@media (spanning: none) and (max-width: 728px) {    
    body {
        flex-direction: column;
    }

    .map {
        flex: 0 0 300px;
    }

    .locations-list {
        flex: 1;
    }
}

如果使用JavaScript可以這樣:

window.onresize = function() {
    const segments = window.getWindowSegments();
    console.log(segments.length) // 1

    if( screenSegments.length > 1 ) {

        document.body.classList.add('is-foldable');
        document.querySelector('.map').classList.add('flex-one-half');
        document.querySelector('.locations-list').classList.add('flex-one-half');
    }
}

實戰:多屏幕布局

最後我們來看實際案例。

你可能在手上沒有摺疊屏或多屏幕的設備,有可能無法看到實際效果。但可以使用一款基於Web的模擬器,這款模擬器可以模擬微軟 Surface Duo 和 Surface Neo兩款分屏設備:

embed: foldable-web-27.mp4

@kenchris 在GitHub上spanning-css-polyfill提供了幾個Demo,我們來看最簡單的basic中的index.html

HTMl部分很簡單(這個Demo本身就很簡單):

<div class="wrapper">
    <div class="col1"></div>
    <div class="col2"></div>
</div>

</body>前加載了一個.js文件,根據CSS Spanning Polyfill提供的一些方法,處理一些全局樣式,甚至可以根據JavaScript的API來構建CSS方面的樣式。

<script type="module" src="../../src/index.js"></script>

index.js對應的詳細代碼可以點擊這裡查閱。

接著看CSS部分。在CSS中使用媒體查詢特性:


/* 普通設備下對應的CSS */
.wrapper {
    display: flex;
    height: 100%;
    width: 100%;
}

.col1 {
    flex: 0 0 200px;
    background-color: lightgray;
    transition: background-color .2s linear;
}

.col2 {
    flex: 1;
    background-color: papayawhip;
    transition: background-color .2s linear;
}

.col1:before {
    content: "not spanning";
}

.col2:before {
    content: "not spanning";
}

不是分屏(或摺疊)設備中,看到的效果像下面這樣:
image.png
在水平方向分屏狀態(即spanning取值為single-fold-vertical)下的CSS:


@media (spanning: single-fold-vertical) {
    .col1 {
        flex: 0 0 env(fold-left);
        margin-right: env(fold-width);
        background-color: steelblue;
    }

    .col2 {
        background-color: yellow;
    }

    .col1:before {
        content: "spanning single-fold-vertical";
    }
    .col2:before {
        content: "spanning single-fold-vertical";
    }
}

注意,示例中還使用了CSS的env()函數,調用了CSS環境變量fold-left和fold-width。這個時候看到的效果如下:
image.png
當你把瀏覽器模式(Browser Mode)切換為“Left”或“Right”時,看到的效果如下:
image.png
上圖是Surface Duo模擬器,Browser Mode為Left狀態效果
image.png
上圖是Surface Duo模擬器,Browser Mode為Right狀態效果

接下來再來設備垂直方向分屏(即spanning取值為single-fold-horizontal)的佈局樣式:


@media (spanning: single-fold-horizontal) {
    .wrapper {
        flex-direction: column;
    }

    .col1 {
        flex: 0 0 env(fold-top);
        margin-bottom: env(fold-height);
        background-color: pink;
    }

    .col2 {
        background-color: seagreen;
    }

    .col1:before {
        content: "spanning single-fold-horizontal";
    }
    .col2:before {
        content: "spanning single-fold-horizontal";
    }
}

image.png
同樣的,如果你把模擬器的瀏覽器模式切換到"Top"或"Bottom"狀態下,看到的效果也會不一樣:
image.png

最後,你還可以在spanning:none狀態下設置相應的CSS:

@media (spanning: none) {
    .col1:before {
      content: "spanning:none";
    }
    .col2:before {
      content: "spanning:none";
    }
}

上面是一個較為簡單的示例。那麼接下來,我們在上面的基礎上把頁面做得稍微複雜一點:

<!-- HTML -->
<ul class="card__container">
    <li class="card">
        <div class="card__object"><img src="//source.unsplash.com/300x300?01" alt="Psychopomp"></div>
        <div class="card__body">
            <h4 class="card__title">Psychopomp</h4>
            <p>Japanese Breakfast</p>
        </div>
    </li>
    <!-- ... -->
</ul>

按照上面的示例,在媒體特性之外,給普通設備添加樣式(也可以說是全局樣式):


/* 佈局關鍵樣式 */
body {
    width: 100vw;
    min-height: 100vh;
    margin: 0;
    padding: 2vh;
}

.card__container {
    gap: 2vmin;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    grid-auto-flow: dense;
}

.card:nth-child(1) {
    grid-column: span 2;
}

.card:nth-child(6) {
    grid-column: span 3;
}

普通設備(非摺疊和分屏)下效果點擊這裡查看。

拖動瀏覽器時改變視窗大小,看到的效果如下:
640 (6).gif
在不對spanning媒體特性下做任何樣式處理時,在分屏狀態下看到的效果如下:
image.png
同樣的,先對spanning: single-fold-vertical做樣式上的處理:

@media (spanning: single-fold-vertical) {

    .card__container {
        gap: env(fold-width);
        grid-template-columns: repeat(auto-fit, minmax(calc((env(fold-left) - env(fold-width) - 4vh) / 2), 1fr));
    }

    .card:nth-child(6) {
        grid-column: span 2;
    }
}

這個時候水平分屏狀態下的效果如下:
640 (7).gif
接著來看垂直方向的分屏狀態下的效果,先來看未處理時的效果:
image.png
接下來在spanning: single-fold-horizontal媒體特性下做一些佈局上的處理:

@media (spanning: single-fold-horizontal) {

    .card__container {
        gap: 20px;
        grid-template-columns: 1fr;
        grid-template-rows: calc(env(fold-height) - 4vh);
    }

    .card__object {
        height: 250px;
    }

    .card:nth-child(1) {
        grid-column: span 1;
    }

    .card:nth-child(6) {
        grid-column: span 1;
    }
}

看到的效果如下:
640 (8).gif
實際操作的時候,應該根據自己的使用場景,然後對應的媒體查詢特性中配合CSS本地環境使用,實現不同的效果。

有關於這方面的Demo,還可以查閱:

小結

可摺疊Web的出現,讓移動優先的設計變得更加複雜,但也更加令人興奮。可摺疊Web可能是第一次手持設備感到空間的擴展而不是限制。對於一些Web應用或Web頁面來說,需要做一定的調整,而對於另一些Web應用來說,則意味著需要大規模的重新設計。這個範圍取決於開發人員的創新。

參考資料


image.png
關注「Alibaba F2E」
把握阿里巴巴前端新動向

Leave a Reply

Your email address will not be published. Required fields are marked *