如何用html css js 画出曲线 或者斜线;
效果图

解题思路
将图片全部定位至中心点,然后x轴就变动translateX ,y轴同理;
这里有两个问题
浏览器: 以左上角为原点0,0 越往下y越大
数学坐标系:以中心点为原点0,0 越往下y越小;
曲线函数:坐标确定了原点确定了,就需要对应的曲线函数来描述这条线段
我们一个个来解决
一、如何把数学坐标系运用到浏览器之中,转化y轴的上下大小反序;
translateX 变化多少就是多少,translateY 变化多少就是反向移动多少,所以重要的是这个反向我们如何来描述,其实这里也很简单,我们使用css变量,然后在变化的时候,setProperty对应的变量值,然后在css里我们做对应的描述;
<style>#container {width: 100vw;height: 100vh;background-color: aqua;position: relative;overflow: auto;}.curveImg {--size: 30px;--dx: 1;--dy: 1;border-radius: calc(var(--size) / 2);width: var(--size);height: var(--size);position: absolute;left: 50%;top: 50%;margin-left: calc(var(--size) / 2);margin-top: calc(var(--size) / 2);object-fit: cover; /* 保持图片纵横比 */transition: all 0.8s ease-out ;transform: translate(calc(var(--dx) * 1px), calc(var(--dy) * -1px));}</style><body><div id="container"></div></body>
此时我们已经完成了准备工作,接着完成反向排序的准备工作,dy越大则在html中排列就越小,超越原点即为负数;
二、将原点挪至中心点
原点在与你想让它在那个位置,它都可以排列到那个位置,这里我想让它在容器内渲染,所以我想设置在容器内的中心位置,那么这个中心位置,其实就是我给定的最大值与最小值和的一半就是我的中心点;
那么我只要让其对应的横坐标点,减去当前的原点,就是它当前需要移动的距离,也就是dx,y同理;
曲线函数
不管是曲线,还是抛物线,还是斜线,其实都是有一个方程式,或者叫做函数来表示;
那么如果是在数学中;
y=x; 那就表示一段45度的斜线;
y=-x ; 那就表示一段-45度的斜线;
y=sin(x); 那就表示连绵的曲线;
数学坐标系中是无限延伸的,但在我们的浏览器中,他是有一个范围呢;所以我们还需要给他一个范围
如果是在代码中,如果我们得到了曲线的表示函数,接下来就是将其用html、css、js来绘制到我们的电脑屏幕中;
我们先来写一个类来表示这个计算类
class Curve {
/** * 创建一个计算类的实例 * * @constructor * @param {Function} curveFunc 要添加的任务实例 * @param {Array} xRange x取值范围* @param {Array} yRange y取值范围*/ constructor(curveFunc, xRange, yRange) {this.xRange = xRangethis.yRange = yRangethis.curveFunc = curveFunc}/*** 计算曲线函数* @param {Number} x x值* @returns {Number} y y值*/getY(x) {let y = this.curveFunc(x)if (y < this.yRange[0]) {y = this.yRange[0]}if (y > this.yRange[1]) {y = this.yRange[1]}return y}
}
上面我们已经创建好一个计算类、具体释义有jsdoc注释;
那么我们如何来表示曲线或者直线呢
const line = new Curve(x=>x,[-1,1],[-1,1])
const wave = new Curve(x => Math.sin(x),[-1 * Math.PI, 3 * Math.PI],[-1, 1]
)
这样就表示出来了;
曲线:y = wave.getY(x);
直线:y = line.getY(x);
那么关于坐标关系我们已经用代码描述出来绘制就是最简单的事了;
<div id="container"></div>
假设我们现在有这么一个div;
然后我们先在div里创建一些图片(当然这里也可以换成你喜欢的样式);
const box = document.querySelector("#container")
const initImg = className => {const frag = document.createDocumentFragment()for (let i = 0; i < 100; i++) {const img = document.createElement("img")img.classList.add(className)img.src = "./test.jpg" // 设置图片路径frag.appendChild(img)}box.appendChild(frag)
}
initImg("curveImg")
接下来就是渲染
const layout = (curve, doms, width, height) => {const [minX, maxX] = curve.xRangeconst [minY, maxY] = curve.yRange// 步长 const xStep = (maxX - minX) / (doms.length - 1)// 与实际坐标轴的比例const xScale = width / (maxX - minX)const yScale = height / (maxY - minY)const cx = (maxX + minX) / 2const cy = (maxY + minY) / 2for (let i = 0; i < doms.length; i++) {const dom = doms[i]const x = minX + i * xStepconst y = curve.getY(x)const dx = (x - cx) * xScaleconst dy = (y - cy) * yScaledom.style.setProperty("--dx", dx)dom.style.setProperty("--dy", dy)}
}
接下来只要我们执行layout函数,那么图片就会进行对应的渲染;
上全部代码
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><style>#container {width: 100vw;height: 100vh;background-color: aqua;position: relative;overflow: auto;}.curveImg {--size: 30px;--dx: 1;--dy: 1;border-radius: calc(var(--size) / 2);width: var(--size);height: var(--size);position: absolute;left: 50%;top: 50%;margin-left: calc(var(--size) / 2);margin-top: calc(var(--size) / 2);object-fit: cover; /* 保持图片纵横比 */transition: all 0.8s ease-out ;transform: translate(calc(var(--dx) * 1px), calc(var(--dy) * -1px));}</style></head><body><div><button onclick="renderLine()">直线</button><button onclick="renderWave()">曲线</button><button onclick="renderLineX()">x线</button><button onclick="renderWaveX()">交叉曲线线</button></div><div id="container"></div><script>class Curve {/*** 创建一个计算类的实例 ** @constructor* @param {Function} curveFunc 要添加的任务实例* @param {Array} xRange x取值范围* @param {Array} yRange y取值范围*/constructor(curveFunc, xRange, yRange) {this.xRange = xRangethis.yRange = yRangethis.curveFunc = curveFunc}/*** 计算曲线函数* @param {Number} x x值* @returns {Number} y y值*/getY(x) {let y = this.curveFunc(x)if (y < this.yRange[0]) {y = this.yRange[0]}if (y > this.yRange[1]) {y = this.yRange[1]}return y}}const layout = (curve, doms, width, height) => {const [minX, maxX] = curve.xRangeconst [minY, maxY] = curve.yRangeconst xStep = (maxX - minX) / (doms.length - 1)const xScale = width / (maxX - minX)const yScale = height / (maxY - minY)const cx = (maxX + minX) / 2const cy = (maxY + minY) / 2for (let i = 0; i < doms.length; i++) {const dom = doms[i]const x = minX + i * xStepconst y = curve.getY(x)const dx = (x - cx) * xScaleconst dy = (y - cy) * yScaledom.style.setProperty("--dx", dx)dom.style.setProperty("--dy", dy)}}const box = document.querySelector("#container")const initImg = className => {const frag = document.createDocumentFragment()for (let i = 0; i < 100; i++) {const img = document.createElement("img")img.classList.add(className)img.src = "./test.jpg" // 设置图片路径frag.appendChild(img)}box.appendChild(frag)}initImg("curveImg")const images = document.querySelectorAll(".curveImg")const wave = new Curve(x => Math.sin(x),[-1 * Math.PI, 3 * Math.PI],[-1, 1])const wave2 = new Curve(x => Math.sin(x),[0 * Math.PI, 4 * Math.PI],[-1, 1])const line = new Curve(x => x, [-1, 1], [-1, 1])const line2 = new Curve(x => -x, [-1, 1], [-1, 1])const middleIndex = Math.floor(images.length / 2)const dom1 = Array.from(images).slice(0,middleIndex);const dom2 = Array.from(images).slice(middleIndex);function renderLine() {layout(line, images, box.clientWidth - 200, box.clientHeight - 200)}function renderWave() {layout(wave, images, box.clientWidth - 200, box.clientHeight - 200)}function renderLineX() {layout(line, dom1, box.clientWidth - 200, box.clientHeight - 200)layout(line2, dom2, box.clientWidth - 200, box.clientHeight - 200)}function renderWaveX() {layout(wave, dom1, box.clientWidth - 200, box.clientHeight - 200)layout(wave2, dom2, box.clientWidth - 200, box.clientHeight - 200)}document.addEventListener("DOMContentLoaded", () => {renderLine()})</script></body>
</html>相关文章:
如何用html css js 画出曲线 或者斜线;
效果图 解题思路 将图片全部定位至中心点,然后x轴就变动translateX ,y轴同理; 这里有两个问题 浏览器: 以左上角为原点0,0 越往下y越大 数学坐标系:以中心点为原点0,0 越往下y越小࿱…...
【错误记录】Uncaught TypeError: m.nodeName.toLowerCase is not a function
描述:在控制台输出上述错误~ 原因:在页面中,使用jQuery 开发时,命名不能和jQuery一起方法属性冲突,比如这里的nodeName,这里换一个不冲突的名字,就解决问题了。...
王颖奇:ONES.ai 上线,以及我的一些思考
ONES.ai 正式上线!为你解锁更智能、更高效的新一代研发管理体验 我们上线了 ONES.ai,当然我们用了公开的 LLM(AI),目前我们最方便使用的就是公开的 LLM,其实是不是 公开的 LLM 也不重要,在未来可预见的时间内ÿ…...
将AI技术与VR元宇宙相结合的整体解决方案
当前人工智能与VR虚拟现实两大热门技术的融合,正引领着人类走向更智能、更数字化、更便捷、更快速的时代。将这两者结合,AI智能检索应用到VR教学中,将为教育带来前所未有的好处。 个性化教学体验 通过AI智能检索,VR教学可以针对每…...
IPKISS Tutorials 3------绘制矩形版图
IPKISS Tutorials 3------绘制矩形版图 方法1------使用Rectangle函数模块导入与放置层设定创建PCell可视化版图这里给大家介绍一下如何在 IPKISS 绘制一个矩形结构的版图。 方法1------使用Rectangle函数 import si_fab.all as pdk import ipkiss3.all as i3class Box(i3.PC…...
为什么需要用高压放大器
高压放大器是一种重要的电子设备,它的主要功能是将高电压信号放大到所需的输出水平。在各种不同的应用中,为什么我们需要使用高压放大器呢?本文将详细探讨以下几个方面的原因。 高压放大器在科学研究中起着关键的作用。在物理学、化学、生物学…...
前端uniapp生成海报绘制canvas画布并且保存到相册【实战/带源码/最新】
目录 插件市场效果如下图注意使用my-share.vue插件文件如下图片hch-posterutilsindex.js draw-demo.vuehch-poster.vue 最后 插件市场 插件市场 效果如下图 注意 主要:使用my-share.vue和绘制canvas的hch-poster.vue这两个使用 使用my-share.vue <template&…...
【算法专题】双指针
双指针 双指针1. 移动零2. 复写零3. 快乐数4. 盛水最多的容器5. 有效三角形的个数6. 和为s的两个数字7. 三数之和8. 四数之和 双指针 常见的双指针有两种形式,⼀种是对撞指针,⼀种是左右指针。 对撞指针:⼀般用于顺序结构中,也称…...
redis运维(七)基础通用命令
一 基础通用命令 备注: 与具体数据类型无关Tab键 自动补全补充: redis 命令是不区分大小写 通用不到 10 个提升逼格的 redis 命令 后续: slowlog、rename-command、monitor、set ① help command 需求: 显示有关redis命令的…...
搜索引擎ElasticSearch分布式搜索和分析引擎学习,SpringBoot整合ES个人心得
ElasticSearch Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎。Elas…...
云原生微服务架构图
云原生微服务架构的具体架构图会根据应用程序的需求、规模和业务场景而有所不同。以下是一个通用的云原生微服务架构图,具体每层的组件可能有所不同: 用户界面层: Web应用或移动应用: 提供用户访问和交互的前端应用。API Gateway&…...
泊车功能专题介绍 ———— AVP系统技术要求之人机交互云平台
文章目录 人机交互车端人机交互车外人机交互灯光交互声音交互 车内人机交互信号装置标示的交互声音交互 场景左右转弯经过让行提示泊入泊出 激活及退出条件激活条件退出条件 场端人机交互V2X交互故障车提醒路口盲区预警弱势交通参与者提醒 场端设施的预警车辆入场车辆故障 APP人…...
精密云工程:智能激活业务速率 ——华为云11.11联合大促倒计时 仅剩3日
现新客3.96元起,下单有机会抽HUAWEI P60 Art,福利仅限双十一,机会唾手可得,立即行动! 双十一购物节来临倒计时,华为云备上多款增值产品,以最优品质迸发冬日技术热浪,满足行业技术应用…...
SpringBoot整合EasyExcel
目录 一、EasyExcel介绍 1、简介 2、常用注解 二、SpringBoot整合EasyExcel 1、基本环境 (1)引入依赖 (2)创建实体类 2、EasyExcel内容读取 (1)创建监听器 (2)测试 3、EasyExcel内容校验 (1)场景描述 (2)EasyExcel监听器 (3)测试 4、EasyExcel内容批量插…...
详解JS遍历数组的十八种方法
for循环 let arr[1,2,3] for(let i0;i<arr.length;i){console.log(arr[i]) }for循环可以遍历数组,它一共有三个参数,第一个参数可以当成数组索引值,想要遍历时候可以设置初始值为0,然后以数组长度为判断依据,如果不…...
Python程序设计基础2
第1关:HUT开学了: # 请在此添加代码 Name = input() # 输入学生的姓名 ########## Begin ########## print("|++++++++++++++++++++++|") print("| |") print("| Welcome to HUT |") print("| …...
域名服务器有哪些类型
域名服务器有哪些类型 随着现在网络的不断发展,越来越多的企业开始使用网络建站,以此来进行营销和推广,而网站在建设过程中需要使用域名和空间,那么域名服务器是什么?下面由给大家说一下。 主域名服务器 负责维护一…...
5.什么是Spring的依赖注入(DI)?IOC和DI的区别是什么
很多人把IOC和DI说成一个东西,笼统来说的话是没有问题的,但是本质上还是有所区别的,希望大家能够严谨一点, IOC和DI是从不同的角度描述的同一件事,IOC是从容器的角度描述,而DI是从应用程序的角度来描述,也…...
Python开源自动化工具Playwright安装及介绍
一个非常强大的自动化项目叫 playwright-python 它支持主流的浏览器,包含:Chrome、Firefox、Safari、Microsoft Edge 等,同时支持以无头模式、有头模式运行,并提供了同步、异步的 API,可以结合 Pytest 测试框架 使用&…...
Nginx生产环境安装配置
不建议使用nginx-1.18.0.tar.gz,因为扫出很多漏洞 上传nginx-1.24.0.tar.gz [rootzonghe01 data]# ll -rw-r--r-- 1 root root 1112471 Oct 26 15:57 nginx-1.24.0.tar.gz [rootzonghe01 data]# pwd /data解押 [rootzonghe01 data]# tar -zxvf nginx-1.24.0.tar…...
为什么Python社区推荐用pipx替代pip?以virtualenv安装为例演示工作流
为什么Python开发者应该用pipx替代pip?以virtualenv为例的完整隔离方案 当你在Ubuntu终端输入pip install virtualenv时,那个刺眼的externally-managed-environment错误提示就像一堵墙——这不是技术故障,而是Python生态进化的重要路标。传统…...
Pyspark环境搭建及案例(Windows)
Windows环境下开发pyspark程序 一、环境准备:Anaconda Python 虚拟环境 1. 安装 Anaconda(推荐) 下载地址:https://www.anaconda.com/products/distribution 安装时选择“Add Anaconda to PATH”会更方便。 2、新建虚拟环境 使…...
基于大数据技术的产品评价分析系统设计与实现
前言本研究聚焦于设计与实现一种基于大数据技术的产品评价分析系统,通过构建多层架构体系与融合多元技术方法,为企业决策提供智能化支撑。 研究采用分层架构设计理念,将系统划分为数据采集、存储、处理、分析与展示五大模块。数据采集层综合运…...
BetterNCM Installer插件管理器:网易云音乐用户的功能扩展工具
BetterNCM Installer插件管理器:网易云音乐用户的功能扩展工具 【免费下载链接】BetterNCM-Installer 一键安装 Better 系软件 项目地址: https://gitcode.com/gh_mirrors/be/BetterNCM-Installer BetterNCM Installer是面向网易云音乐PC用户的插件管理工具&…...
douyin-downloader:3大核心能力破解抖音内容高效下载难题
douyin-downloader:3大核心能力破解抖音内容高效下载难题 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback su…...
2026学生免费用AI编程神器全攻略——白嫖不要白不要,大学生快来
好的,上一章刚教你用GitHub武装自己,筑起技术护城河,但光会搬砖(敲命令)还不够,你得学会“开高达”——用AI编程助手把效率拉满。 2026年了,如果还纯靠手打for循环和查API文档,那你…...
Nunchaku-flux-1-dev参数详解:CFG Scale、种子数等关键参数实战影响
Nunchaku-flux-1-dev参数详解:CFG Scale、种子数等关键参数实战影响 你是不是也遇到过这样的情况:用同一个模型,别人生成的图片细节满满、创意十足,而你生成的却总是差点意思,要么太放飞自我,要么又过于死…...
智能农业大棚设计详解
基于单片机的智能农业大棚设计温湿度二氧化碳光照(详细设计说明 10119-基于单片机的智能农业大棚设计温湿度二氧化碳光照(详细设计说明书proteus源代码原理图元件清单) 功能需求: 智慧农业大棚的底层理念是实现智能化控制与生产&a…...
Qwen3-14B私有部署镜像算法题求解助手:从理解到实现
Qwen3-14B私有部署镜像算法题求解助手:从理解到实现 1. 为什么算法工程师需要AI助手 算法工程师和求职者每天都要面对各种算法问题,从简单的排序到复杂的动态规划。传统方式下,我们需要反复查阅资料、手动编写测试用例、调试代码࿰…...
显卡驱动深度清理指南:用DDU解决驱动残留难题
显卡驱动深度清理指南:用DDU解决驱动残留难题 【免费下载链接】display-drivers-uninstaller Display Driver Uninstaller (DDU) a driver removal utility / cleaner utility 项目地址: https://gitcode.com/gh_mirrors/di/display-drivers-uninstaller 你是…...
