研究了Web版Photoshop,提升自己=提升价值

news2024/11/16 0:35:17

Adobe 发布了Web版 Photoshop🔗,它是使用 WebAssembly、web components、P3 颜色等 Web 技术构建的。本文就来研究一下网页版 Photoshop 上有趣又有用的 CSS 知识!

图片

Photoshop 旧 Logo

首先,在浏览器控制台中使用了 Photoshop 的 Logo(1990-1991)。

图片

这是如何实现的呢?这里是代码:

 
console.info(
  "%c %cAdobe %cPhotoshop Web%c  %c2023.20.0.0%c  %c1bba617e276",
  "padding-left: 36px; line-height: 36px; background-image: url('data:image/gif;base64,R0lGODlhIAAgAPEBAAAAAPw==');"
)

Body 元素

要让像Photoshop这样的应用在Web上感觉像一个真正的应用,第一件事是防止滚动。为了实现这一点,<body>元素具有position: fixedoverflow: hidden

 
body,
html {
  height: 100%;
}

body {
  font-family: adobe-clean, sans-serif;
  margin: 0;
  overflow: hidden;
  position: fixed;
  width: 100%;
}

<body>元素内部,也有多个根元素。

 
<psw-app>
  <psw-app-context>
    <ue-video-surface>
      <ue-drawer>
        <div id="appView">
          <psw-app-navbar></psw-app-navbar>
          <psw-document-page></psw-document-page>
        </div>
      </ue-drawer>
    </ue-video-surface>
  </psw-app-context>
</psw-app>

最内部有一个包含导航和文档页面的元素。

 
#appView {
  background-color: var(--editor-background-color);
  color: var(--spectrum-global-color-gray-800);
  display: flex;
  flex-direction: column;
}

图片

 
* {
  touch-action: manipulation;
}

:host {
  position: relative;
}

Flexbox 布局

在构建现代的 Web 应用时,使用 Flex 布局具有很多好处。网页版 Photoshop 就用到了很多 Flex 布局。

图片

使用 Flexbox 使构建组件变得更容易。下面来看几个使用 Flexbox 的例子。

导航栏

我很喜欢这部分的元素类命名,它没有使用 leftcenterright,而是使用了startcenterend

图片

在应用可以从左到右(LTR)或从右到左(RTL)工作时,这种逻辑命名是正确的做法。

操作

在构建像 Photoshop 这样的复杂应用时,嵌套的 Flexbox 容器是很常见的。下图显示了操作栏中的两个容器。

图片

第一个容器用于缩放。第二个容器包含所有的操作和按钮。

 
.container {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--spectrum-global-dimension-size-50);
}
  • 使用gap属性非常有助于定义间距,使用marginpadding来实现这个效果可能会变得混乱。

  • .container这个类名太过通用了,但在这里非常适用,因为这是一个Web组件,所以所有的样式都被封装起来了。

图层

图层功能是Photoshop的重要组成部分,仔细观察CSS,发现它们全部都是 Flexbox 布局。

图片

下面是图层组件的 HTML 结构:

 
<psw-tree-view-item indent="0" layer-visible can-open dir="ltr" open>
  <div id="link">
    <span id="first-column"></span>
    <span id="second-column"></span>
    <span id="label"></span>
  </div>
</psw-tree-view-item>

这里使用 ID 是完全没问题的,因为这是一个 Web 组件,因此 #first-column ID 在页面上出现多少次并不重要。

图片

#link元素是一个 Flexbox 容器,#label元素也是一个 Flexbox 容器。

 
<div class="layer-content layer-wrapper selected">
  <psw-layer-thumbnail></psw-layer-thumbnail>
  <div class="name" title="Layer name">Layer name</div>
  <div class="actions"></div>
  <overlay-trigger></overlay-trigger>
</div>

下面来举一个例子说明如何完成子层的缩进。

图片

  • :host()表示图层组件。

  • 这感觉像是条件式 CSS。如果HTML属性indent=1存在,那么就更改第一列的padding-right

 
:host([dir="ltr"][indent="1"]) #first-column {
  padding-right: var(--spectrum-global-dimension-size-200);
}

如果缩进是两个级别,那么可以通过CSS的calc()函数,将padding-right的值乘以 2。

 
:host([dir="ltr"][indent="2"]) #first-column {
  padding-right: calc(2 * var(--spectrum-global-dimension-size-200));
}

在浏览器中,尝试嵌套到第 6 层:

图片

而知名的设计软件 Figma 是使用间隔组件来增加嵌套层的间距的。

图片

Grid 布局

新文件模式

在创建新的 Photoshop 文件时,可以选择预定义的尺寸列表。为了实现这一点,有一个包含多个选项卡和一个活动面板的布局。

图片

HTML 如下所示:

 
<sp-tabs
  id="tabs"
  quiet=""
  selected="2"
  size="m"
  direction="horizontal"
  dir="ltr"
  focusable=""
>
  <div id="list"></div>
  <slot name="tab-panel"></slot>
</sp-tabs>

在 CSS 中,有一个 1 列 2 行的主网格。其中,第一行的高度根据内容自适应调整行高,而第二行则占据了所有剩余可用空间。

 
:host {
  display: grid;
  grid-template-columns: 100%;
}

:host(:not([direction^="vertical"])) {
  grid-template-rows: auto 1fr;
}

这里有几个要点:

  • 使用CSS的:not()选择器。

  • 使用[attr^=value]选择器来排除具有以vertical开头的值的direction属性的HTML元素。

这些都是条件式 CSS 技术。

尝试将direction属性更改为vertical,结果符合预期。

图片

下面是基于属性变化的CSS:

 
:host([direction^="vertical"]) {
  grid-template-columns: auto 1fr;
}

:host([direction^="vertical-right"]) #list #selection-indicator,
:host([direction^="vertical"]) #list #selection-indicator {
  inline-size: var(
    --mod-tabs-divider-size,
    var(--spectrum-tabs-divider-size)
  );
  inset-block-start: 0px;
  inset-inline-start: 0px;
  position: absolute;
}

为了突出显示哪个选项卡是活动状态,有一个相对于选项卡列表定位的#selection-indicator元素。

图层属性

这部分的 CSS 网格用法很有趣,它适合解决对齐网格中许多元素的问题。

图片

深入研究 CSS:

 
.content {
  position: relative;
  display: grid;
  grid-template-rows: [horizontal] min-content [vertical] min-content [transforms] min-content [end];
  grid-template-columns: [size-labels] min-content [size-inputs] auto [size-locks] min-content [space] min-content [position-labels] min-content [position-inputs] auto [end];
  row-gap: var(--spectrum-global-dimension-size-150);
}

使用 Firfox 开发者工具来调试这个网格,它会生成模拟的网格布局。当突出显示矩形时,它将显示放置在实际的网格中。

图片

这里使用的技术就是命名网格线,其思想是给每个列或行指定一个名称,然后定义其宽度。列和行的宽度可以是automin-content,这是创建动态网格的一种很好的方法。

图片

这样,每个网格项都可以在网格内部进行定位:

 
.horizontal-size-label {
  grid-area: horizontal / size-labels / horizontal / size-labels;
}

.vertical-position-input {
  grid-area: vertical / position-inputs / vertical / position-inputs;
}

.horizontal-position-input {
  grid-area: horizontal / position-inputs / horizontal /
    position-inputs;
}

还有一个细节是对网格项使用了position: absolute。锁定按钮位于网格的中心,但它需要略微从左边和顶部位置进行插入。

 
.lock-button {
  grid-area: horizontal / size-locks / horizontal / size-locks;
  position: absolute;
  left: 8px;
  top: 22px;
}

输入

下面来看看使用 CSS 网格来布局输入字段的用例。

 
:host([editable]) {
  display: grid;
  grid-template-areas:
    "label ."
    "slider number";
  grid-template-columns: 1fr auto;
}

:host([editable]) #label-container {
  grid-area: label / label / label / label;
}

:host([editable]) #label-container + div {
  grid-area: slider / slider / slider / slider;
}

:host([editable]) sp-number-field {
  grid-area: number / number / number / number;
}

在浏览器中检查时,可以看到网格线名称或网格区域名称。

  • 网格区域名称

图片

  • 网格线名称

图片

菜单项

图片

在我看来,在这里使用 CSS 网格有点大材小用了。

 
sp-menu-item {
  display: grid;
  grid-template-areas:
    ". chevronAreaCollapsible . iconArea sectionHeadingArea . . ."
    "selectedArea chevronAreaCollapsible checkmarkArea iconArea labelArea valueArea actionsArea chevronAreaDrillIn"
    ". . . . descriptionArea . . ."
    ". . . . submenuArea . . .";
  grid-template-columns: auto auto auto auto 1fr auto auto auto;
  grid-template-rows: 1fr auto auto auto;
}

这是一个包含 8列 4行的网格。这里似乎一次只能激活一个网格行,其他行将由于内容为空或HTML元素的缺失而折叠。

有趣的是,上面的 CSS 是简化过的版本。原始版本看起来像这样,使用了grid-template缩写。

图片

下面是在应用中找到的一些菜单项:

图片

CSS 网格是针对这个小组件的,感觉是有点多此一举了。

 
.checkmark {
  align-self: start;
  grid-area: checkmarkArea / checkmarkArea / checkmarkArea /
    checkmarkArea;
}

#label {
  grid-area: labelArea / labelArea / labelArea / labelArea;
}

::slotted([slot="value"]) {
  grid-area: valueArea / valueArea / valueArea / valueArea;
}

图片

注意,CSS 网格的暗部分处于非活动状态。它们折叠了,因为没有内容。对于这个例子,也可以这样来实现:

 
.checkmark {
  align-self: start;
  grid-area: checkmarkArea;
}

#label {
  grid-area: labelArea;
}

::slotted([slot="value"]) {
  grid-area: valueArea;
}

当每列和行的值相同时,无需定义它们的开始和结束位置。

CSS变量的广泛使用

更改图层缩略图的大小

Photoshop 可以控制缩略图大小。当有很多图层并且想要在更小的空间中查看更多图层时,这非常有用。

图片

Adobe 团队的构建方式很有趣。首先,图层面板的主容器上有一个 HTML 属性large-thumbs

 
<psw-layers-panel large-thumbs></psw-layers-panel>

在CSS中,有一个:host([large-thumbs])选择器,它分配了特定的CSS变量。

 
:host([large-thumbs]) {
  --psw-custom-layer-thumbnail-size: var(
    --spectrum-global-dimension-size-800
  );
  --psw-custom-layer-thumbnail-border-size: var(
    --spectrum-global-dimension-size-50
  );
}

对于每个图层,都有一个名为 psw-layer-thumbnail 的元素,这是将应用CSS变量的地方。

 
<psw-layers-panel-item>
  <psw-tree-view-item>
    <psw-layer-thumbnail class="thumb"></psw-layer-thumbnail>
  </psw-tree-view-item>
</psw-layers-panel-item>

这里,CSS 变量被分配给缩略图。

 
:host {
  --layer-thumbnail-size: var(
    --psw-custom-layer-thumbnail-size,
    var(--spectrum-global-dimension-size-400)
  );
  --layer-badge-size: var(--spectrum-global-dimension-size-200);
  position: relative;
  width: var(--layer-thumbnail-size);
  min-width: var(--layer-thumbnail-size);
  height: var(--layer-thumbnail-size);
}

加载进度

通过使用size属性来管理组件的大小。CSS 变量会根据不同的 size 而变化。

图片

 
:host([size="m"]) {
  --spectrum-progressbar-size-default: var(
    --spectrum-progressbar-size-2400
  );
  --spectrum-progressbar-font-size: var(--spectrum-font-size-75);
  --spectrum-progressbar-thickness: var(
    --spectrum-progress-bar-thickness-large
  );
  --spectrum-progressbar-spacing-top-to-text: var(
    --spectrum-component-top-to-text-75
  );
}

图像控制

如果 HTML 存在属性quiet,则 UI 会更简单(没有边框)。

图片

这也是通过 CSS 变量完成的。

 
:host([quiet]) {
  --spectrum-actionbutton-background-color-default: var(
    --system-spectrum-actionbutton-quiet-background-color-default
  );
  --spectrum-actionbutton-background-color-hover: var(
    --system-spectrum-actionbutton-quiet-background-color-hover
  );
}

单选按钮

在这个例子中,使用 CSS 变量来根据 HTML 的 size 属性值来改变单选按钮的大小。

图片

 
<sp-radio size="m" checked="" role="radio"></sp-radio>
 
:host([size="m"]) {
  --spectrum-radio-height: var(--spectrum-component-height-100);
  --spectrum-radio-button-control-size: var(
    --spectrum-radio-button-control-size-medium
  );
}

菜单处于活动状态时锁定页面

当主菜单处于活动状态时,会有一个名为 holder 的元素填充整个屏幕(遮罩层),并位于菜单下方。

图片

 
#actual[aria-hidden] + #holder {
  display: flex;
}

#holder {
  display: none;
  align-items: center;
  justify-content: center;
  flex-flow: column;
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
}

此元素是为了防止用户单击或将鼠标悬停在页面的其他部分,以确保用户只能对菜单进行操作,这可能是为了模仿桌面应用而设置的。

混合模式菜单

这里使用了 CSS 视口单位。混合模式菜单的最大高度为 55vh(视口高度的55%)。

图片

 
sp-menu {
  max-height: 55vh;
  --mod-menu-item-min-height: auto;
}

::slotted(*) {
  overscroll-behavior: contain;
}

这里还使用了 overscroll-behavior: contains,这是避免滚动正文内容的一个很棒的功能。

图片

图层缩略图

在图层面板中,缩略图使用了object-fit: contain来避免变形。

图片

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1376913.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数字人】9、DiffTalk | 使用扩散模型基于 audio-driven+对应人物视频 合成说话头(CVPR2023)

论文&#xff1a;DiffTalk: Crafting Diffusion Models for Generalized Audio-Driven Portraits Animation 代码&#xff1a;https://sstzal.github.io/DiffTalk/ 出处&#xff1a;CVPR2023 特点&#xff1a;需要音频对应人物的视频来合成新的说话头视频&#xff0c;嘴部抖…

基于python的Hurst计算预测未来发展趋势(长时序栅格影像)

1.Hurst指数反映了时间序列长期记忆性的程度&#xff0c;即过去的信息对未来的影响程度。Hurst指数的取值范围为0到1之间&#xff0c;当Hurst指数等于0.5时&#xff0c;时间序列被认为是一种随机漫步&#xff0c;即具有随机性&#xff1b;当Hurst指数大于0.5时&#xff0c;时间…

JAVA基础学习笔记-day17-反射

JAVA基础学习笔记-day17-反射 1. 反射(Reflection)的概念1.1 反射的出现背景1.2 反射概述1.3 Java反射机制研究及应用1.4 反射相关的主要API1.5 反射的优缺点 2. 理解Class类并获取Class实例2.1 理解Class2.1.1 理论上2.1.2 内存结构上 2.2 获取Class类的实例(四种方法)2.3 哪些…

【MySQL】本地创建MySQL数据库详解

文章目录 下载MySQL安装重置密码本地连接 下载MySQL 下载网址&#xff1a;https://dev.mysql.com/downloads/mysql/ 安装 将下载好的压缩包解压到D盘。 在解压好的文件夹中创建my.ini文件。 将以下代码复制粘贴到创建好的my.ini文件中。注意修改文件路径。 [mysqld] #设置…

重生奇迹MU装备升级材料的获取

在重生奇迹MU中&#xff0c;装备升级需要使用各种材料&#xff0c;包括经验章、神秘石、宝石、元素石等。以下是各种材料的获取方法。 经验章&#xff1a;经验章是装备升级的基础材料&#xff0c;可以通过打怪掉落、任务奖励、商城购买等方式获得。建议玩家们多参加游戏中的活…

Python——python练习题

1.小明身高1.75&#xff0c;体重80.5kg。请根据BMI公式&#xff08;体重除以身高的平方&#xff09;帮小明计算他的BMI指数&#xff0c;并根据BMI指数&#xff1a; 低于18.5&#xff1a;过轻 18.5-25&#xff1a;正常 25-28&#xff1a;过重 28-32&#xff1a;肥胖 高于32&…

(Arcgis)matlab编程批量处理hdf4格式转换为tif格式

国家青藏高原科学数据中心 中国区域1km无缝地表温度数据集&#xff08;2002-2020&#xff09; 此代码仅用于该数据集处理 版本&#xff1a;arcgis10.2 matlab2020 参考&#xff1a;MATLAB hdf(h5)文件转成tif图片格式&#xff08;批量处理&#xff09; 此代码仅用于该数据集处…

SecLists:安全测试人员的必备手册 | 开源日报 No.144

danielmiessler/SecLists Stars: 50.9k License: MIT SecLists 是安全测试人员的伴侣&#xff0c;它是一个收集了多种类型列表的项目&#xff0c;用于安全评估。这些列表包括用户名、密码、URL、敏感数据模式、模糊负载、Web shell 等。其目标是使安全测试人员能够将该存储库拉…

SV-9001 壁挂式网络采播终端

SV-9001 壁挂式网络采播终端 一、描述 SV-9001是深圳锐科达电子有限公司的一款壁挂式网络采播终端&#xff0c;具有10/100M以太网接口&#xff0c;配置一路线路输入和一组麦克风输入&#xff0c;可以直接连接音源输出设备或麦克风&#xff0c;将采集音源编码后发送至网络播放终…

腾讯云COS桶文件上传下载工具类

1&#xff0c;申请key和密钥 2&#xff0c;引入依赖 <dependency><groupId>com.qcloud</groupId><artifactId>cos_api</artifactId><version>5.6.24</version></dependency>3&#xff0c;工具类 package com.example.activi…

跨境商城系统如何开发代购商城、国际物流、一件代发等功能?

跨境商城系统的开发涉及到多个方面&#xff0c;其中代购商城、国际物流和一件代发等功能是其中的重要组成部分。本文将详细介绍如何开发这些功能&#xff0c;以帮助跨境商城系统更好地满足市场需求。 一、代购商城的开发 代购商城是跨境商城系统中的重要功能之一&#xff0c;它…

怎么将文件批量重命名为不同名称?

怎么将文件批量重命名为不同名称&#xff1f;有许多情况下可以考虑对文件进行批量重命名为不同名称&#xff0c;文件分类和整理&#xff1a;当您需要对一组文件进行分类、整理或重新组织时&#xff0c;可以考虑将它们批量重命名为不同的名称。这有助于更好地组织文件并使其更易…

【JaveWeb教程】(22) MySQL数据库开发之多表查询:内连接、外连接、子查询 详细代码示例讲解(最全面)

目录 数据库开发-MySQL1. 多表查询1.1 概述1.1.1 数据准备1.1.2 介绍1.1.3 分类 1.2 内连接1.3 外连接1.4 子查询1.4.1 介绍1.4.2 标量子查询1.4.3 列子查询1.4.4 行子查询1.4.5 表子查询 1.5 案例 数据库开发-MySQL 1. 多表查询 1.1 概述 1.1.1 数据准备 SQL脚本&#xff…

品牌出海新篇章:DTC营销与红人矩阵的完美结合

随着全球市场的竞争日益激烈&#xff0c;品牌在出海过程中面临着前所未有的挑战。传统的销售渠道逐渐显得滞后&#xff0c;DTC模式正成为品牌开拓国际市场的新趋势。在这一趋势中&#xff0c;结合红人矩阵的DTC营销策略备受关注&#xff0c;为品牌打开了一扇通向全球市场的大门…

【笔记------freemodbus】一、stm32的裸机modbus-RTU从机移植(HAL库)

freemodbus的官方介绍和下载入口&#xff0c;官方仓库链接&#xff1a;https://github.com/cwalter-at/freemodbus modbus自己实现的话往往是有选择的支持几条指令&#xff0c;像断帧和异常处理可能是完全不处理的&#xff0c;用freemodbus实现的话要简单很多&#xff0c;可移植…

2023年国庆节深圳市节假日人口迁出数据,shp/excel格式

基本信息 数据名称: 深圳市节假日人口迁出数据 数据格式: Shp、excel 数据时间: 2023年国庆节 数据几何类型: 线 数据坐标系: WGS84 数据来源&#xff1a;网络公开数据 数据字段&#xff1a; 序号字段名称字段说明1a0928迁出人口占迁出深圳市人口的比值&#xff08…

大模型实战作业03

大模型实战作业03 注&#xff1a; 因为微调数据较少&#xff0c;没有显示出个人助手的名字

GIS融合之路(五)番外-山海鲸的体积云又又又升级了

一转眼自上一篇文章已经过去半年之久&#xff0c;承诺的CesiumJS的天气文章竟然又又又又跳票了&#xff0c;没办法。开发任务时间紧&#xff0c;任务重。GIS的进一步整合进入深水区&#xff0c;每向前迈一步都是步履维艰&#xff0c;好不容易把体积雾&#xff0c;接触阴影&…

[SpringBoot]如何在一个普通类中获取一个Bean

最近在项目中出现了一个这种情况&#xff1a;我一顿操作猛如虎的写了好几个设计模式&#xff0c;然后在设计模式中的类中想将数据插入数据库&#xff0c;因此调用Mapper持久层&#xff0c;但是数据怎么都写不进去&#xff0c;在我一顿操作猛如虎的查找下&#xff0c;发现在普通…

创新奖肯定,这家LIMS您要留意了

近日&#xff0c;龙源电力的“风电化学监督LIMS信息化管理系统的研发与应用”项目荣获中国电力技术市场协会2023年电力行业技术监督创新成果一等奖。系统可为风电设备经济、环保、长周期安全运行提供保障&#xff0c;是国内首套新能源行业油液监测信息管理系统&#xff0c;经中…