图形系统开发实战课程:进阶篇(上)——3.图层类(Layer)


[

图形开发学院|GraphAnyWhere

  • 课程名称:图形系统开发实战课程:进阶篇(上)
  • 课程章节:“图层类(Layer)”
  • 原文地址:https://graphanywhere.com/graph/advanced/2-3.html

第三章:图层类(Layer)

\quad 在上一章中,我们讲到了图层(Layers)是一种用于组织和管理图像内容的办法。可以将不同的图像元素分开,使得它们可以独立地进行绘制、编辑和操作。每个图层都可以包含一个或多个图像对象,这些对象可以是几何对象、文本、图像等。图层可以互相叠加,并且可以通过控制透明度、颜色和大小等属性来创建各种视觉效果。

\quad 本章以 anyGraph 中图层类的设计为例讲述图层在图形中的作用。

1. 类的设计

\quad 面向对象程序设计中的抽象是指从具体事物中抽取其共性的过程。按照这个方法,我们对图层的属性、数据和行为进行分析后,归纳出在图形系统中,图层的特征可分为三类:图层属性、图层数据、图层渲染。图层属性包括图层名称、渲染顺序、可见范围等信息,图层数据包含了该图层中的图形对象集合,图层渲染是指将图形对象集合渲染至画板Canvas中的操作。

\quad 这三个特征可分别对应一个Class,在其封装内部逻辑,这三个类命名分别为Layer类LayerSource类LayerRenderer类,这三者的关系如下图所示:

Layer
LayerRenderer
LayerSource

\quad 按照上一章对图形的定义,一个图形包含了多个图层,负责图层的集合管理。集合中每个图层均包含了上述三个类的实例。

类关系图

\quad 按照数据类型差异,图层的数据源可以是几何数据源,可以是位图数据源,也可以是地图瓦片数据源。数据类型的差异会导致在渲染时采用不同的渲染方法,因此图层数据源图层渲染是一种强对应关系,例如图层矢量数据源VectorSource对应的是图层矢量渲染类VectorRenderer类,图层瓦片数据源TileSource对于图层瓦片渲染类TileRenderer

\quad 下面这张类图包含了这几个类及其父类。

BaseSource
dataBuffer:Array
imageBuffer:Array
getData()
getLayer()
VectorSource
format: GeometryFormat
loadData(features)
add(geomList)
clearData(id)
getExtentData(extent)
getBBox()
buildIndex()
TileSource
loadData(features)
add(geomList)
clearData(id)
ImageSource
loadData(features)
add(geomList)
clearData(id)
LayerRenderer
_canvas: Canvas
composeBuffer()
ImageRenderer
_canvas:Canvas
_getRenderedImages()
composeBuffer(frameState)
TileRenderer
_canvas:Canvas
_getRenderedTiles()
composeBuffer(frameState)
VectorRenderer
_canvas:Canvas
prepareFrame()
composeBuffer(frameState)
renderFrame()
clearContext(ctx)
setStyle()
filter()
Layer
zIndex: int
name: String
style: Object
opacity: float
source: BaseSource
usePixelCoord: boolean
renderer: LayerRenderer
setStyle(style)
getVisible()
visibleAtResolution()
setOffset(x, y)

2. 图层类

类名为:Layer,源代码位于src目录。

\quad 图层类 Layer 是图层中这几个类的核心类,提供了图层信息、图层控制、图层样式等方面的功能。

(1) 初始化

constructor(options)

\quad 该类的构造函数接受一个 Object 类型的参数,其值包括:

名称类型说明
nameString名称
zIndexint图层顺序,zIndex较大的图层显示在较小的图层之上
usePixelCoordBoolean是否使用像素作为坐标
opacityfloat透明度,取值范围为 0~1
minResolutionfloat图层可见的最小密度
maxResolutionfloat图层可见的最大密度
visibleBoolean图层是否可见
styleObject图层样式
sourceSource图层数据源

下面是创建一个图层的示例:

let layer = new Layer({source: new VectorSource({"fileUrl": path + "export_roadcenter.geojson","projection": projection,"format": new GeoJSONFormat()}),zIndex: 10025,name: "道路-路中线",style: { "color": "#00BFFF", "lineWidth": 2 },minResolution: 0.880,maxResolution: 3.240,visible: true
});
graph.addLayer(layer);

(2) 图层信息

下面列出了几个常用的获取图层信息的方法:

名称说明
getName()名称
getZIndex()图层顺序
isUsePixelCoord()是否使用像素作为坐标
渲染顺序

\quad 该属性在构造函数中通过 zIndex属性指定,通过 getZIndex() 可获取图层的渲染顺序。在将图层合成至图形时,先绘制该值较小的图层,然后绘制该值较大的图层。

是否采用像素坐标

\quad 该属性在构造函数中通过 usePixelCoord 属性指定,通过 isUsePixelCoord() 可获取该图层是否采用像素坐标。采用像素坐标时,该图层不会进行矩阵变换,而是直接渲染至Canvas指定位置,这也意味着该图层中的图形位置和大小不会随着图形的缩放和漫游而发生变化。之前多个示例的效果图中都包含了一个带有网格和水印的背景层,就设置了usePixelCoord=true,因此不管对图形进行怎样的缩放和漫游操作,其背景始终是不变的。

(3) 图层控制

下面列出了几个图层控制的方法:

名称说明
getVisible()是否显示
setVisible(visible)设置是否显示
getMaxResolution()获取最大分辨率值
setMaxResolution(maxResolution)设置渲染该图层的最大分辨率值
getMinResolution()获取最小分辨率值
setMinResolution(minResolution)设置渲染该图层的最小分辨率值
可见性

\quad 该属性可在构造函数中通过 visible 属性指定 或 通过 setVisible() 设置图层可见性。如果该值为false,则不合成至图形中。

分辨率

\quad 分辨率指的Canvas中像素对应图形的宽度/高度的比值,通过分辨率属性同样可以控制图层的可见性。在构造函数中可指定最小分辨率 minResolution 和 最大分辨率 maxResolution 属性指定。

  1. 在地图图纸中通常使用 比例尺 来描述地图的精度,比例尺是表示图上一条线段的长度与地面相应线段的实际长度之比。公式为:比例尺=图上距离/实际距离。一般来讲,越是大的比例尺地图,几何精度越高。
  2. 而在计算中通常使用 分辨率 来描述地图的精度,分辨率指的Canvas中1个像素对应图形的宽度/高度的比值。同样分辨率越大,几何精度越高。
  3. 在计算机中通常不采用比例尺来描述图形的精度,这是因为“比例尺=图上距离/实际距离",而显示器屏幕的大小是不确定的,同一张图在14寸的显示器上和27寸的显示器上显示全图时,由于分母相同分子不相同,因此其比值是不一样的。

(4) 图层样式

名称说明
getStyle()获取图层渲染样式
setStyle(style)设置图层渲染样式
getOpacity()获取图层透明度 (between 0 and 1).
setOpacity(opacity)设置透明度(between 0 and 1)

\quad 该属性在构造函数中通过 style 属性指定,也可通过 setStyle(style) 方法赋值。样式主要指的是几何对象的颜色、线宽、线型等渲染时的属性,而对于文字而言,样式还包括文本的大小、字型、对齐等属性。

\quad 在渲染图层中的图形对象时,既可以为图层中的每一个图形对象指定样式,也可以为图层指定样式。如果图形对象和图层均指定了样式,则优先使用图形对象的样式。

3 数据源

\quad 图层数据包含了某图层渲染时的图形对象集合,该集合中的所有对象都位于同一个坐标系中。

\quad 该属性在构造函数中通过 source 属性指定,缺省为 VectorDataSource 类型, 图层类 Layer 提供了getSource() 方法可获取该图层对应的数据源对象。

名称说明
getSource()获取图层数据源

(1) 矢量数据源

类名为:VectorDataSource,位于src/source目录。

\quad 矢量数据源是为矢量图层提供具体的数据来源,包含了在图形上展示几何对象和文本、图像等图形对象集合。

初始化
constructor(options)

\quad 该类的构造函数接受一个 Object 类型的参数,其值包括:

名称类型说明
formatFeatureFormat格式化对象
fileUrlString数据文件Url
dataArray数据列表
projectionProjection投影类型对象

说明:

  • format 属性,用于在 loadFile()loadData() 时解析数据的格式化对象;
  • data 属性,如果指定了该属性,则构造后立即将该数据装载至 Source 中,优先级高于 fileUrl 属性;
  • fileUrl 属性,如果指定了该属性,则构造后立即下载该数据文件,并装载至 Source 中;
  • projection 属性,如果指定了该属性,则从 datafileUrl 加载数据时,将进行坐标投影变换。

\quad 下面这个示例在构造VectorSource时,指定了 fileUrl 属性,因此在构造之后,数据将渲染至图形中。

<script type="module">import { Graph, VectorSource, Layer, debug } from "../../../src/index.js";// graph对象let graph = new Graph({"target": "graphWrapper","layers": [new Layer({"source": new VectorSource({"fileUrl": "../../../data/geom.json"})})]});// 图形渲染graph.render();
</script>
属性
名称说明
dataBuffer矢量数据集合
imageBuffer图像数据集合
quadTree空间索引对象
format格式化对象

这几个属性中 dataBufferimageBufferquadTree均属于内部对象。

\quad format 对象是 FeatureFormat 类的实例,该对象可将外部矢量数据解析为 anyGraph 所使用的内部数据格式, 缺省值为GeometryFormat。可在构造VectorDataSource 实例时指定 format 属性,或是通过 setFormat(format) 指定 format 属性。

方法
名称说明
add(geom)增加Geomtory对象至数据源中
loadFile(fileUrl, success, failure)从文件中读取矢量数据
loadData(features)装载Geomtory数据至数据源中
clearData(id)清除指定ID数据,如果ID为空则清除数据源中所有数据
buildIndex()构建四叉树索引
getExtentData(extent)获取指定范围内的数据
getBBox()获取数据源中的最大空间范围
add2Cache(filePath, imageUid)将图片数据加至缓存中
getImageFromCache(src)从缓存中获取Image对象
loadImage(src, callback, callback)加载Image对象
toData(options = {})以矢量数据格式返回当前数据源中的数据

\quad 下面介绍几个常用的方法:

loadFile()

\quad 该方法下载数据文件通过format对象解析后,加载至 Source 中。

loadFile(fileUrl, success, failure)

\quad 下面这个示例,将从Url中下载数据文件,通过缺省的format对象解析后装载至VectorSource中,并进行图形渲染。

<script type="module">import { Graph, VectorSource, Layer, debug } from "../../../src/index.js";// 初始化graph对象let graph = new Graph({"target": "graphWrapper",});// 增加数据层let layer = graph.addLayer({"name":"数据层"});layer.getSource().loadFile("../../../data/geom.json");// 图形渲染graph.render();
</script>

\quad 该方法从文件中读取矢量数据,该方法通过XMLHttpRequest从指定的fileUrl中下载文件,并通过format对象解析文件中的图形对象。

loadData()

\quad 该方法将矢量数据通过format对象解析后,加载至 Source 中。

loadData(features)

\quad 下面这个示例,将数据通过缺省的format对象解析后装载至VectorSource中,并进行图形渲染。

<script type="module">import { Graph, Layer, VectorSource, debug, DomUtil } from "../../../src/index.js";// 初始化graph对象let graph = new Graph({"target": "graphWrapper"});// 增加数据层       let layer = graph.addLayer({"name":"数据层"});layer.getSource().loadData([{ "type": "Polygon", "coords": [[1, 1], [161, 1], [81, 81]], "style": { "fillStyle": 1, "fillColor": "#caff67" } },{ "type": "Polygon", "coords": [[1, 2], [81, 82], [1, 162]], "style": { "fillStyle": 1, "fillColor": "#67becf" } },{ "type": "Polygon", "coords": [[162, 1], [162, 81], [122, 121], [122, 41]], "style": { "fillStyle": 1, "fillColor": "#ef3d61" } },{ "type": "Polygon", "coords": [[121, 42], [121, 122], [81, 82]], "style": { "fillStyle": 1, "fillColor": "#f9f51a" } },{ "type": "Polygon", "coords": [[82, 82], [122, 122], [82, 162], [42, 122]], "style": { "fillStyle": 1, "fillColor": "#a54c09" } },{ "type": "Polygon", "coords": [[42, 122], [82, 162], [2, 162]], "style": { "fillStyle": 1, "fillColor": "#fa8ccc" } },{ "type": "Polygon", "coords": [[162, 82], [162, 162], [82, 162]], "style": { "fillStyle": 1, "fillColor": "#f6ca29" } }]);// 图形渲染graph.render();
</script>
add()

add(geom)

\quad 该方法将一个或多个Geometry的对象加入数据源中。

buildIndex()

buildIndex()

\quad 该方法将建立空间索引。建立空间索引可以提高检测视点范围内数据的效率,排除视点外的数据,缩短图形的渲染时间,特别适合大数据量的情况。在loadFile()中会自动调用该方法建立空间索引。

toData()

toData(options = {})

\quad 该方法将返回当前数据源中Geometry对象JSON格式数据,可用于数据持久化。

数据格式

\quad 矢量数据源 VectorDataSource 在装载数据的时候,可以根据 Format 对象装载不同格式的数据,anyGraph1.0可支持的格式包括:

  • Geometry对象格式,其Format数据类为 GeometryFormat 类,这也是 VectorDataSource 的缺省数据格式。
  • GeoJSON格式,一种很常用的地理空间数据交换格式,其Format数据类为 GeoJSONFormat类。
  • SVG格式,可缩放矢量图形(Scalable Vector Graphics)是一种基于XML的矢量图像格式,其Format数据类为 SvgFormat类。
  • CIMG(CIM/G)格式,是国家电网公司发布一种基于CIM的图形交换格式,其Format数据类为 CimgFormat类。
  • AXFG格式,是一种很经典的基于json的图形交换格式,其Format数据类为 AxfgFormat类。

下面的示例将装载和显示一个SVG格式文件,其源代码如下:

<!DOCTYPE html>
<html>
<head><title>SVG</title><meta http-equiv="content-type" content="text/html; charset=utf-8"><script type="module">import { Graph, VectorSource, Layer, SvgFormat, debug } from "../../src/index.js";// 数据源let fileUrl = "../../data/flower.svg";// graph对象let graph = new Graph({"target": "graphWrapper","layers": [new Layer({"source": new VectorSource({"dataType": "xml","fileUrl": fileUrl,"format": new SvgFormat()})})]});// 显示辅助网格debug.generateGrid(Object.assign({ "interval": 10, "graph": graph }, graph.getSize()));</script>
</head>
<body style="overflow: hidden; margin:0px;" oncontextmenu="return false;"><div id="graphWrapper" style="position:absolute; width:100%; height:100%; border:solid 0px #CCC;"></div>
</body>
</html>

该代码运行后将在浏览器中全屏显示一幅SVG图形,其运行效果如下图:

在这里插入图片描述

(2) 图像数据源

(3) 瓦片数据源

4 图层渲染

图层渲染负责将数据集合中的图形对象渲染至画板Canvas中,图层类 Layer 提供了getRenderer() 方法可获取该图层对应的图层渲染器对象。

名称说明
getRenderer()获取取图层渲染器

(1) 矢量数据图层渲染

类名为:VectorRenderer,位于src/renderer目录。

\quad 矢量数据图层渲染类负责将图层中 VectorSource 数据渲染至图层的Canvas画布中。

\quad 该类中最重要的属性是 _canvas ,这是一个Canvas对象,是该图层的临时画布,图层中的数据先由 composeBuffer() 方法合成至该临时画布中,然后在合并至图形主画布中。

\quad 该类中最重要的方法是 composeBuffer(frameState),该方法由 GraphRenderer 负责调用,将数据合成至Canvas画布,其主要分为三个步骤。

  1. 根据 frameState 参数中的 extent 属性(当前显示范围)从 DataSource 查询 Geometry对象 数据,如果 DataSource 建立了空间索引,该步骤将极大提高数据检索效率;

  2. 对这些 Geometry对象 数据进行坐标变换,将图形坐标转换为Canvas画布中的像素坐标;

  3. 逐个将这些 Geometry对象 数据绘制至Canvas画布中。

\quad 步骤二中的将 Geometry对象 的图形坐标转换为像素坐标功能,由于不同类型的 Geometry对象 其空间属性不相同,因此其转换方法不相同;步骤三中逐个将 Geometry对象 绘制至Canvas画布中也因为不同类型的 Geometry对象 其绘制方法不相同。因此我们根据Geometry 对象类型设计了针对其类型的 Geometry 子类,这些子类均从 Geometry 继承, 在各个子类中实现了将图形坐标转换为像素坐标的 toPixel() 方法和图形绘制 draw() 方法,关于这部分的详细介绍我们将在下一章 “图形基本形状” 中进行讲解。

(2) 图像数据图层渲染

(3) 瓦片数据图层渲染


\quad “图形系统实战开发-进阶篇 第三章 图层” 的内容讲解到这里就结束了,如果觉得对你有帮助有收获,可以关注我们的官方账号,持续关注更多精彩内容。

相关资料

▶ 系列教程及代码资料:https://GraphAnyWhere.com
▶ 图形系统开发实战课程:进阶篇(上)——前言
▶ 图形系统开发实战课程:进阶篇(上)——1.基础知识
▶ 图形系统开发实战课程:进阶篇(上)——2.图形管理类(Graph)


作者信息

作者 : 图形开发学院
CSDN: https://blog.csdn.net/2301_81340430?type=blog
官网:https://graphanywhere.com

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

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

相关文章

代码随想录算法训练营Day55|392.判断子序列、115.不同的子序列

目录 392.判断子序列 思路 ​算法实现 115.不同的子序列 思路 算法实现 总结 392.判断子序列 题目链接 文章链接 思路 利用动规五部曲进行分析&#xff1a; 1.确定dp数组及其下标含义&#xff1a; dp[i][j] 表示以下标i-1为结尾的字符串s&#xff0c;和以下标j-1为结尾的…

寒假作业:2024/2/11

作业1&#xff1a;使用递归实现n! 代码&#xff1a; #include <stdio.h> #include <string.h> #include <stdlib.h> int fun(int n) {if(0n){return 1;}else{return n*fun(n-1);} } int main(int argc, const char *argv[]) {int n;printf("please en…

深入浅出CChart 每日一课——红花当然配绿叶,CChart辅助图形绘制

各位同学&#xff0c;好久不见&#xff0c;我可想死你们了&#xff01;&#xff01;&#xff01;咦&#xff0c;那位不是巩叔吗&#xff1f;不好意思&#xff0c;侵权了&#xff0c;请多担待_。 前面的课程呢&#xff0c;拓展的内容比较多&#xff0c;最近笨笨想聚焦在CChart本…

车载电子电器架构 —— 电子电气系统功能开发

车载电子电器架构 —— 电子电气系统功能开发 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 本就是小人物,输了就是输了,不要在意别人怎么看自己。江湖一碗茶,喝完再挣扎,出门靠自己,四海皆…

C++三剑客之std::optional(一) : 使用详解

相关文章系列 C三剑客之std::optional(一) : 使用详解 C三剑客之std::any(一) : 使用 C之std::tuple(一) : 使用精讲(全) C三剑客之std::variant(一) : 使用 C三剑客之std::variant(二)&#xff1a;深入剖析 目录 1.概述 2.构建方式 2.1.默认构造 2.2.移动构造 2.3.拷贝构…

C#计算矩形面积:通过定义结构 vs 通过继承类

目录 一、涉及到的知识点 1.结构 2.结构和类的区别 3.继承 4.使用类继承提高程序的开发效率 5.属性 &#xff08;1&#xff09;属性定义 &#xff08;2&#xff09;get访问器 &#xff08;3&#xff09;set访问器 6. 属性和字段的区别 二、实例&#xff1a;通过定义…

[word] word表格表头怎么取消重复出现? #媒体#笔记#职场发展

word表格表头怎么取消重复出现&#xff1f; word表格表头怎么取消重复出现&#xff1f;在Word中的表格如果过长的话&#xff0c;会跨行显示在另一页&#xff0c;如果想要在其它页面上也显示表头&#xff0c;更直观的查看数据。难道要一个个复制表头吗&#xff1f;当然不是&…

idea:如何连接数据库

1、在idea中打开database: 2、点击 ‘’ ---> Data Source ---> MySQL 3、输入自己的账号和密码其他空白处可以不填&#xff0c;用户和密码可以在自己的mysql数据库中查看 4、最后选择自己需要用的数据库&#xff0c;点击运用ok&#xff0c;等待刷新即可 最后&#xff1a…

springboot179基于javaweb的流浪宠物管理系统的设计与实现

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

disql备份还原

disql备份还原 前言 本文档根据官方文档&#xff0c;进行整理。 一、概述 在 disql 工具中使用 BACKUP 语句你可以备份整个数据库。通常情况下&#xff0c;在数据库实例配置归档后输入以下语句即可备份数据库&#xff1a; BACKUP DATABASE BACKUPSET db_bak_01;语句执行完…

C++进阶(十四)智能指针

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、为什么需要智能指针&#xff1f;二、内存泄漏1、 什么是内存泄漏&#xff0c;内存泄漏的危…

量子位 | 2024年AI还能帮你干什么?这十个趋势必须关注

本文来源公众号“量子位”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;2024年AI还能帮你干什么&#xff1f;这十个趋势必须关注 大年初三&#xff0c;也不要忘记学习&#xff01;新的一年里&#xff0c;怎样能让AI多给自己帮帮…

【数据结构】13:表达式转换(中缀表达式转成后缀表达式)

思想&#xff1a; 从头到尾依次读取中缀表达式里的每个对象&#xff0c;对不同对象按照不同的情况处理。 如果遇到空格&#xff0c;跳过如果遇到运算数字&#xff0c;直接输出如果遇到左括号&#xff0c;压栈如果遇到右括号&#xff0c;表示括号里的中缀表达式已经扫描完毕&a…

每日一练:LeeCode-654、最大二叉树【二叉树+DFS+分治】

本文是力扣LeeCode-654、最大二叉树【二叉树DFS分治】 学习与理解过程&#xff0c;本文仅做学习之用&#xff0c;对本题感兴趣的小伙伴可以出门左拐LeeCode。 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点&#xff0c;其…

python安装cv2失败

问题:安装cv2包失败 解决方法&#xff1a; pip install opencv-python或在Anaconda中conda install opencv-python

蓝牙BLE学习-蓝牙广播

1.概念 什么叫做广播&#xff0c;顾名思义就像广场上的大喇叭一样&#xff0c;不停的向外传输着信号。不同的是&#xff0c;大喇叭传输的是音频信号&#xff0c;而蓝牙传输的是射频信号。 BLE使用的是无线电波传递信息&#xff0c;就是将数据编码&#xff0c;调制到射频信号中发…

基于Robei EDA--实现串口通信

一、串口简介 串口作为常用的三大低速总线&#xff08;UART、SPI、IIC&#xff09;之一&#xff0c;在设计众多通信接口和调试时占有重要地位。但UART和SPI、IIC不同的是&#xff0c;它是异步通信接口&#xff0c;异步通信中的接收方并不知道数据什么时候会到达&#xff0c;所…

【后端高频面试题--SpringBoot篇】

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;后端高频面试题 &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; 这里写目录标题 1.什么是SpringBoot&#xff1f;它的主要特点是什么&#xff1f;2.列举一些Spri…

《CSS 简易速速上手小册》第4章:视觉美学(2024 最新版)

文章目录 4.1 颜色理论在 CSS 设计中的应用&#xff1a;网页的调色盘4.1.1 基础知识4.1.2 重点案例&#xff1a;创建一个具有情感设计的登录页面4.1.3 拓展案例 1&#xff1a;使用颜色增强信息的可视化表示4.1.4 拓展案例 2&#xff1a;利用颜色创建网站的品牌身份 4.2 字体与文…