CSS线性渐变拼接,一个完整的渐变容器(div),要拆分成多个渐变容器(div),并且保持渐变效果一致
1 需求
一个有渐变背景的div,需要替换成多个渐变背景div拼接,渐变效果需要保持一致(不通过一个大的div渐变,其他子的div绝对定位其上并且背景透明来解决)
2 分析
主要工作:
- 计算完整div背景线性渐变时的渐变开始线和结束线(假设中心点为几何中心)
- 计算各个独立div背景线性渐变时的渐变开始线和结束线(假设中心点为几何中心)
- 重新计算各个子div的渐变开始线和结束线(百分比)
3 实现
3.1 水平拼接

解释:
- 黑色虚线为各个子div的水平和垂直中心线
- 红色虚线为整个div的水平和垂直中心线
- 绿色虚线为渐变方向上的中心线,和黑色虚线的夹角为各个子div的渐变角
- 紫色虚线为渐变方向上的中心线,和红色虚线的夹角为整个div的渐变角
- 蓝色虚线为渐变开始线和结束线,垂直于渐变方向上的中心线
- 蓝色圆为各个子div独立渐变时的渐变起始中心点,绿色圆为各个子div独立渐变时的渐变结束中心点
- 紫色圆为整个div的渐变起始中心点,红色圆为整个div的渐变结束中心点
- 蓝色紫色双圆为当前子div独立渐变时和其作为整个div整体渐变的一部分时的共同渐变起始中心点,是重合的
- 绿色红色双圆为当前子div独立渐变时和其作为整个div整体渐变的一部分时的共同渐变结束中心点,是重合的
- 蓝色实线段为整个渐变路径,其长度为渐变长度,也就是颜色值后面的参数0-100%
- 绿色实线段为为了作为整体渐变一部分而需要增加的渐变路径
<template><div class="container gradient"></div><div class="container"><divclass="container-column"v-for="(col, index) in itemList":key="index":style="{width: col.width + 'px',height: col.height + 'px',background: getGradient(col, index)}"></div></div>
</template><script setup lang="ts">
const itemList = ref([{width: 100,height: 400},{width: 200,height: 400},{width: 300,height: 400}
]);
const angle = ref(45);const getGradient = (item, index) => {const beforeWidth = itemList.value.slice(0, index).reduce((a, b) => a + b.width, 0);const afterWidth = itemList.value.slice(index + 1).reduce((a, b) => a + b.width, 0);const startPosition = `calc(100% - (${beforeWidth} * sin(${angle.value}deg) / (2 * (${item.width / 2} * tan(${angle.value}deg) + ${item.height / 2}) * cos(${angle.value}deg)) + 1) * 100%)`;const endPosition = `calc((${afterWidth} * sin(${angle.value}deg) / (2 * (${item.width / 2} * tan(${angle.value}deg) + ${item.height / 2}) * cos(${angle.value}deg)) + 1) * 100%)`;const ret = `linear-gradient(${angle.value}deg,red ${startPosition},blue ${endPosition})`;return ret;
};
</script>
<style scoped lang="scss">
.container {width: 600px;height: 400px;display: inline-block;.container-column {display: inline-block;}
}
.gradient {background: linear-gradient(45deg, red 0%, blue 100%);
}
</style>
效果:

加上边框更清晰点:

3.2 垂直拼接

解释:
- 黑色虚线为各个子div的水平和垂直中心线
- 红色虚线为整个div的水平和垂直中心线
- 绿色虚线为渐变方向上的中心线,和黑色虚线的夹角为各个子div的渐变角
- 紫色虚线为渐变方向上的中心线,和红色虚线的夹角为整个div的渐变角
- 蓝色虚线为渐变开始线和结束线,垂直于渐变方向上的中心线
- 蓝色圆为各个子div独立渐变时的渐变起始中心点,绿色圆为各个子div独立渐变时的渐变结束中心点
- 紫色圆为整个div的渐变起始中心点,红色圆为整个div的渐变结束中心点
- 蓝色紫色双圆为当前子div独立渐变时和其作为整个div整体渐变的一部分时的共同渐变起始中心点,是重合的
- 绿色红色双圆为当前子div独立渐变时和其作为整个div整体渐变的一部分时的共同渐变结束中心点,是重合的
- 蓝色实线段为整个渐变路径,其长度为渐变长度,也就是颜色值后面的参数0-100%
- 绿色实线段为为了作为整体渐变一部分而需要增加的渐变路径
<template><div class="container gradient"></div><div class="container"><divclass="container-column"v-for="(col, index) in itemList":key="index":style="{width: col.width + 'px',height: col.height + 'px',background: getGradient(col, index)}"></div></div>
</template><script setup lang="ts">
const itemList = ref([{width: 400,height: 100},{width: 400,height: 200},{width: 400,height: 300},{width: 400,height: 300}
]);
const angle = ref(45);const getGradient = (item, index) => {const afterHeight = itemList.value.slice(0, index).reduce((a, b) => a + b.height, 0);const beforeHeight = itemList.value.slice(index + 1).reduce((a, b) => a + b.height, 0);const startPosition = `calc(100% - (${beforeHeight} * cos(${angle.value}deg) / (2 * (${item.width / 2} * tan(${angle.value}deg) + ${item.height / 2}) * cos(${angle.value}deg)) + 1) * 100%)`;const endPosition = `calc((${afterHeight} * cos(${angle.value}deg) / (2 * (${item.width / 2} * tan(${angle.value}deg) + ${item.height / 2}) * cos(${angle.value}deg)) + 1) * 100%)`;const ret = `linear-gradient(${angle.value}deg,red ${startPosition},blue ${endPosition})`;return ret;
};
</script>
<style scoped lang="scss">
.container {width: 400px;height: 900px;display: inline-block;& + .container {margin-left: 10px;}line-height: 0;.container-column {display: inline-block;}
}
.gradient {background: linear-gradient(45deg, red 0%, blue 100%);
}
</style></style>
效果:

加上边框更清晰点:

3.3 矩阵拼接

图上画线太多,下图画个稍微简明点的

解释:
- 黑色虚线为各个子div的水平和垂直中心线
- 红色虚线为整个div的水平和垂直中心线
- 绿色虚线为渐变方向上的中心线,和黑色虚线的夹角为各个子div的渐变角
- 紫色虚线为渐变方向上的中心线,和红色虚线的夹角为整个div的渐变角
- 蓝色虚线为渐变开始线和结束线,垂直于渐变方向上的中心线
- 蓝色圆为各个子div独立渐变时的渐变起始中心点,绿色圆为各个子div独立渐变时的渐变结束中心点
- 紫色圆为整个div的渐变起始中心点,红色圆为整个div的渐变结束中心点
- 蓝色紫色双圆为当前子div独立渐变时和其作为整个div整体渐变的一部分时的共同渐变起始中心点,是重合的
- 绿色红色双圆为当前子div独立渐变时和其作为整个div整体渐变的一部分时的共同渐变结束中心点,是重合的
- 蓝色实线段为整个渐变路径,其长度为渐变长度,也就是颜色值后面的参数0-100%
- 绿色实线段为为了作为整体渐变一部分而需要增加的渐变路径
<template><div class="container gradient"></div><div class="container"><div class="container-row" v-for="(row, rowIndex) in itemList" :key="rowIndex"><divclass="container-column"v-for="(col, colIndex) in row":key="colIndex":style="{width: col.width + 'px',height: col.height + 'px',background: getGradient(col, colIndex, rowIndex)}"></div></div></div>
</template><script setup lang="ts">
const itemList = ref([[{width: 100,height: 100},{width: 300,height: 100}],[{width: 200,height: 200},{width: 100,height: 200},{width: 100,height: 200}],[{width: 100,height: 300},{width: 100,height: 300},{width: 100,height: 300},{width: 100,height: 300}],[{width: 400,height: 300}]
]);
const angle = ref(45);const getGradient = (item, colIndex, rowIndex) => {const afterHeight = itemList.value.slice(0, rowIndex).reduce((a, b) => a + b[0].height, 0);const beforeHeight = itemList.value.slice(rowIndex + 1).reduce((a, b) => a + b[0].height, 0);const beforeWidth = itemList.value[rowIndex].slice(0, colIndex).reduce((a, b) => a + b.width, 0);const afterWidth = itemList.value[rowIndex].slice(colIndex + 1).reduce((a, b) => a + b.width, 0);const startPosition = `calc(100% - ((${beforeHeight} * cos(${angle.value}deg) + ${beforeWidth} * sin(${angle.value}deg))/ (2 * (${item.width / 2} * tan(${angle.value}deg) + ${item.height / 2}) * cos(${angle.value}deg)) + 1) * 100%)`;const endPosition = `calc(((${afterHeight} * cos(${angle.value}deg) + ${afterWidth} * sin(${angle.value}deg)) / (2 * (${item.width / 2} * tan(${angle.value}deg) + ${item.height / 2}) * cos(${angle.value}deg)) + 1) * 100%)`;const ret = `linear-gradient(${angle.value}deg,red ${startPosition},blue ${endPosition})`;return ret;
};
</script>
<style scoped lang="scss">
.container {width: 400px;height: 900px;display: inline-block;& + .container {margin-left: 10px;}.container-row {line-height: 0;.container-column {display: inline-block;}}
}
.gradient {background: linear-gradient(45deg, red 0%, blue 100%);
}
</style>
效果:

加上边框更清晰点:

4 最后
还可以有更复杂的情况:
- 矩阵中的跨行跨列,大家可自行探索(其实投篮的办法是可以把跨行跨列的单元再进行拆分,使得所有单元都不出现跨行跨列,那么上面第三种矩阵拼接就可以使用了)
- 多个颜色(中间的颜色需要根据当前百分比位置和增加的距离得到最终的百分比位置)
- 非线性渐变的情况(感觉稍微有点复杂)
相关文章:
CSS线性渐变拼接,一个完整的渐变容器(div),要拆分成多个渐变容器(div),并且保持渐变效果一致
1 需求 一个有渐变背景的div,需要替换成多个渐变背景div拼接,渐变效果需要保持一致(不通过一个大的div渐变,其他子的div绝对定位其上并且背景透明来解决) 2 分析 主要工作: 计算完整div背景线性渐变时的…...
【60天备战软考高级系统架构设计师——第十天:软件设计与架构综合练习】
经过前十天的学习,我们已经了解了软件工程生命周期模型、需求分析与管理方法,以及软件设计与架构的核心内容。为了巩固这些知识点,今天我们将进行一个综合练习。 前十天学习内容回顾 第1-3天:软件工程概述 学习了软件生命周期模…...
2024.8.15(python管理mysql、Mycat实现读写分离)
一、python管理mysql 1、搭建主mysql [rootmysql57 ~]# tar -xf mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz [rootmysql57 ~]# cp -r mysql-5.7.44-linux-glibc2.12-x86_64 /usr/local/mysql [rootmysql57 ~]# rm -rf /etc/my.cnf [rootmysql57 ~]# mkdir /usr/local/mysql…...
CMU 10423 Generative AI:lec2
文章目录 1 概述2 部分摘录2.1 噪声信道模型(Noisy Channel Models)主要内容:公式解释:应用举例: 2.2 n-Gram模型1. 什么是n-Gram模型2. 早期的n-Gram模型3. Google n-Gram项目4. 模型规模与训练数据5. n-Gram模型的局…...
恋爱相亲交友系统源码原生源码可二次开发APP 小程序 H5,web全适配
直播互动:平台设有专门的直播间,允许房间主人与其他异性用户通过视频连线的方式进行一对一互动。语音视频交流:异性用户可以发起语音或视频通话,以增进了解和交流。群组聊天:用户能够创建群聊,邀请自己关注…...
OceanBase 4.x 存储引擎解析:如何让历史库场景成本降低50%+
据国际数据公司(IDC)的报告显示,预计到2025年,全球范围内每天将产生高达180ZB的庞大数据量,这一趋势预示着企业将面临着更加严峻的海量数据处理挑战。随着数据日渐庞大,一些存储系统会出现诸如存储空间扩展…...
js 如何写构造函数 ,构造函数和普通函数有什么区别
在 JavaScript 中,构造函数是一种特殊的函数,用于初始化一个新创建的对象。构造函数通常用来创建具有相似属性和方法的对象实例。构造函数的主要特点是在调用时使用 new 关键字,这样就会创建一个新对象,并将其原型设置为构造函数的…...
MySQL-进阶篇-锁(全局锁、表级锁、行级锁)
文章目录 1. 锁概述2. 全局锁2.1 介绍2.2 数据备份2.3 使用全局锁造成的问题 3. 表级锁3.1 表锁3.1.1 语法3.1.2 读锁3.1.3 写锁3.1.4 读锁和写锁的区别 3.2 元数据锁(Meta Data Lock,MDL)3.3 意向锁3.3.1 案例引入3.3.2 意向锁的分类 4. 行级…...
c++懒汉式单例模式(Singleton)多种实现方式及最优比较
前言 关于C懒汉式单例模式的写法,大家都很熟悉。早期的设计模式中有代码示例。比如: class Singleton {private: static Singleton *instance;public: static Singleton *getInstance() {if (NULL instance)instance new Singleton();return instanc…...
Gartner《2024中国安全技术成熟度曲线》AI安全助手代表性产品:开发者安全助手D10
海云安关注到,近日,国际权威研究机构Gartner发布了《2024中国安全技术成熟度曲线》(Hype Cycle for Security in China,2024)报告。 在此次报告中,安全技术成熟度曲线将安全周期划分为技术萌芽期(Innovation Trigger)…...
奇安信椒图--服务器安全管理系统(云锁)
奇安信椒图–服务器安全管理系统(云锁) 椒图 奇安信服务器安全管理系统是一款符合Gartner定义的CWPP(云工作负载保护平台)标准、EDR(终端检测与响应)、EPP终端保护平台(终端保护平台ÿ…...
pointer-events,添加水印的一个小小点
场景:平平无奇一个水印图,这类功能实现:就是覆盖在整个可视div后,又加了一个div(使用定位canvas画一个水印图充当背景),可时我好奇的是,我使用控制台,选择对应的元素时&a…...
微服务--认识微服务
微服务架构的演变 1. 单体架构(Monolithic) 阶段描述:在单体应用时代,整个应用程序被设计为一个项目,并在一个进程内运行。这种架构方式开发简单,便于集中管理,但随着应用的复杂化,…...
【docker】docker 镜像仓库的管理
Docker 仓库( Docker Registry ) 是用于存储和分发 Docker 镜像的集中式存储库。 它就像是一个大型的镜像仓库,开发者可以将自己创建的 Docker 镜像推送到仓库中,也可以从仓库中拉取所需的镜像。 Docker 仓库可以分为公共仓…...
第L2周:机器学习-线性回归
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 目标: 学习简单线性回归模型和多元线性回归模型通过代码实现:通过鸢尾花花瓣长度预测花瓣宽度 具体实现: (一&…...
SpringMVC拦截器深度解析与实战
引言 Spring MVC作为Spring框架的核心模块之一,主要用于构建Web应用程序和RESTful服务。在Spring MVC中,拦截器(Interceptor)是一种强大的机制,它允许开发者在请求处理流程的特定点插入自定义代码,实现诸如…...
直线上最多的点数
优质博文:IT-BLOG-CN 题目 给你一个数组points,其中points[i] [xi, yi]表示X-Y平面上的一个点。求最多有多少个点在同一条直线上。 示例 1: 输入:points [[1,1],[2,2],[3,3]] 输出:3 示例 2: 输入&am…...
经济管理专业数据库介绍
本文介绍了四个经济管理专业数据库:国研网全文数据库、EPS数据平台、中经网、Emerald全文期刊库(管理学)。 一、国研网全文数据库 国研网是国务院发展研究中心主管、北京国研网信息有限公司承办的大型经济类专业网站。国研网教育版”是国研…...
【C++ Primer Plus习题】11.1
问题: 解答: main.cpp #include <iostream> #include <fstream> #include "Vector.h" #include <time.h> using namespace std; using namespace VECTOR;int main() {ofstream fout;fout.open("randwalk.txt");srand(time(0));double d…...
[数据库][oracle]ORACLE EXP/IMP的使用详解
导入/导出是ORACLE幸存的最古老的两个命令行工具,其实我从来不认为Exp/Imp是一种好的备份方式,正确的说法是Exp/Imp只能是一个好的转储工具,特别是在小型数据库的转储,表空间的迁移,表的抽取,检测逻辑和物理…...
基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...
