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

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-tabsid="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.hqwc.cn/news/342713.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

揭秘虾皮API接口:开启电商开发新篇章,引领业务增长潮流

虾皮API接口技术详解 一、概述 虾皮API接口是虾皮电商平台为开发者提供的一套应用程序接口&#xff0c;允许第三方开发者通过编程方式访问虾皮平台上的商品、订单、用户等数据&#xff0c;并执行相关操作。通过使用虾皮API接口&#xff0c;开发者可以快速构建与虾皮平台集成的…

2024-1-12 关于SVPWM的理解疑问

直流母线电压利用率是指逆变电路(电机控制器)所能输出的交流电压基波最大幅值U1m和直流母线电压之比。 电压利用率 SVPWM算法理解(二)——关于非零基本矢量幅值和线电压幅值的解释 因此我们在实际应用中提供的直流侧电压Udc,应该大于等于所需要输出的三相相电压幅值的√…

基于springboot+vue的网上花卉商城系统(Java毕业设计)

大家好&#xff0c;我是DeBug&#xff0c;很高兴你能来阅读&#xff01;作为一名热爱编程的程序员&#xff0c;我希望通过这些教学笔记与大家分享我的编程经验和知识。在这里&#xff0c;我将会结合实际项目经验&#xff0c;分享编程技巧、最佳实践以及解决问题的方法。无论你是…

公司寄快递教程

公司寄快递用哪个更划算&#xff1f;这个问题有最优解吗&#xff1f;恐怕没有......很简单&#xff0c;回答这个问题之前&#xff0c;我们先来看看公司寄快递的背景。 一、大背景 所谓的大背景是由国内快递行业的发展现状所决定的。众所周知&#xff0c;这十年来&#xff0c;国…

SpringBoot 源码解析4:refresh 方法解析

SpringBoot 源码解析4&#xff1a;refresh 方法解析 1. refresh 方法解析2. 准备刷新 AbstractApplicationContext#prepareRefresh3. 获取bean工厂 AbstractApplicationContext#obtainFreshBeanFactory4. 准备bean工厂 AbstractApplicationContext#prepareBeanFactory5. Servle…

React项目搭建流程

第一步 利用脚手架创建ts类型的react项目&#xff1a; 执行如下的命令&#xff1a;create-react-app myDemo --template typescript &#xff1b; 第二步 清理项目目录结构&#xff1a; src/ index.tsx, app.txs, react-app-env.d.ts public/index.ht…

教程-右键用vscode(新窗口)打开文件或目录

通过本文可以提高效率&#xff0c;用起来更爽更高效。 本文实现了&#xff08;windows系统&#xff09;&#xff1a; 右键-用vscode(当前窗口)打开文件或目录右键-用vscode-新窗口打开文件或目录 注意&#xff1a; 下面的安装路径要更改为您实际的路径 具体配置步骤&#x…

一键转换,创新无限:将HTML轻松转化为PDF!

在数字时代&#xff0c;HTML与PDF已成为信息传递的两大主流格式。然而&#xff0c;在这两者之间转换常常让人感到困扰。现在&#xff0c;有了我们的创新工具&#xff0c;您只需轻点一下&#xff0c;即可一键将HTML转化为PDF&#xff01; 首先&#xff0c;我们要进入首助编辑高…

(超详细)3-YOLOV5改进-添加SE注意力机制

1、在yolov5/models下面新建一个SE.py文件&#xff0c;在里面放入下面的代码 代码如下&#xff1a; import numpy as np import torch from torch import nn from torch.nn import initclass SEAttention(nn.Module):def __init__(self, channel512,reduction16):super()._…

羊奶的奶源,解密优质健康的来源

羊奶的奶源&#xff0c;解密优质健康的来源 羊奶一直被视为高品质、健康的乳制品&#xff0c;备受消费者的喜爱。作为一位消费者&#xff0c;你一定也想了解羊奶的奶源&#xff0c;究竟是如何保障了这种优质与健康呢&#xff1f;下面小编羊大师就带大家一同了解一下。 我们需…

Python 爬虫常用的库或工具推荐

在数据驱动的时代&#xff0c;Python爬虫技术以其简单易用、强大灵活的特性成为数据采集的有效手段&#xff0c;越来越多人加入了学习Python的队伍中&#xff0c;今天&#xff0c;我们就为大家推荐一些常用的Python爬虫库和工具&#xff0c;以备不时之需。 1.库 Requests库&am…

抽奖机制模型及算法

抽奖机制 连抽保底概率模型不中概率加大模型&#xff08;抽卡保底&#xff09; 抽奖概率为n%&#xff0c;在达到某次次数后&#xff0c;每次概率比上次高m%&#xff0c;直至达到保底次数&#xff08;概率累加和为100%&#xff09;&#xff0c;当抽到极品道具时候&#xff0c;…