使用css实现任意大小,任意方向, 任意角度的箭头

匿名网络
• 阅读 4944

使用css实现任意大小,任意方向, 任意角度的箭头

网页开发中,经常会使用到 下拉箭头使用css实现任意大小,任意方向, 任意角度的箭头,右侧箭头使用css实现任意大小,任意方向, 任意角度的箭头 这样的箭头。 一般用css来实现:

    {  
        display: inline-block;  
        margin: 72px;  
        border-top: 24px solid;
        border-right: 24px solid;  
        width: 120px;
        height: 120px;  
        transform: rotate(45deg); 
    } 

因为这是利用div的border-top, border-right,然后通过旋转div来实现的。

任意角度的箭头

这里有个问题: 假如需要一个角度为120度的箭头怎么办呢? 由于border-top, border-right一直是90度, 所以仅仅通过旋转不行。
我们可以先把div 旋转45度, 让它成为一个 菱形 然后再伸缩,达到任意的角度, 这样就可以得到一个 任意角度的箭头。由于用到了旋转和伸缩两种变换,所以需要使用
transform: matrix(a,b,c,d,e,f) 这个变换矩阵。 这里的6个变量组成了一个3介的变换矩阵

$$ \left[ \begin{matrix} a & c & e \\ b & d & f \\ 0 & 0 & 1 \end{matrix} \right] $$

任意点p(x,y)的平移, 旋转, 伸缩变换以及他们的各种组合都可以通过这个变换矩阵做到:

$$ \left[ \begin{matrix} x \\ y \\ 1 \end{matrix} \right] \left[ \begin{matrix} a & c & e \\ b & d & f \\ 0 & 0 & 1 \end{matrix} \right]= \left[ \begin{matrix} x' \\ y' \\ 1 \end{matrix} \right] $$

注:这里用齐次坐标 来表达一个点。 简单说就是p(x, y) 表示为p'(x', y', 1)

平移矩阵

v(x, y) 沿着x轴平移tx, 沿着y轴平移ty。 则有:

x' = x + tx
y' = y + ty

所以平移矩阵:

$$ \left[ \begin{matrix} x' \\ y' \\ 1 \end{matrix} \right]= \left[ \begin{matrix} 1 & 0 & tx \\ 0 & 1 & ty \\ 0 & 0 & 1 \end{matrix} \right] \left[ \begin{matrix} x \\ y \\ 1 \end{matrix} \right] $$

旋转矩阵

v(x, y) 点绕原点旋转θ到v'(x', y')
使用css实现任意大小,任意方向, 任意角度的箭头
则有:

x = r * cos(ϕ )
y = r * sin(ϕ )

x' = r * cos(θ + ϕ) = r * cos(θ) * cos(ϕ) - r * sin(θ) * sin(ϕ ) // 余弦公式
y' = r * sin(θ + ϕ) = r * sin(θ) * cos(ϕ) + r * cos(θ) * sin(ϕ ) // 正弦公式

所以:

x' = x * cos(θ) - y * sin(θ)
y' = x * sin(θ) + y * cos(θ)

所以旋转矩阵:

$$ \left[ \begin{matrix} x' \\ y' \\ 1 \end{matrix} \right]= \left[ \begin{matrix} cos(θ) & -sin(θ) & 0 \\ sin(θ) & cos(θ) & 0 \\ 0 & 0 & 1 \end{matrix} \right] \left[ \begin{matrix} x \\ y \\ 1 \end{matrix} \right] $$

伸缩矩阵

假设x轴,y轴的伸缩率分别是kx, ky。 则有:

x' = x * kx
y' = y * ky

所以:

$$ \left[ \begin{matrix} x' \\ y' \\ 1 \end{matrix} \right]= \left[ \begin{matrix} kx & 0 & 0 \\ 0 & ky & 0 \\ 0 & 0 & 1 \end{matrix} \right]= \left[ \begin{matrix} x \\ y \\ 1 \end{matrix} \right] $$

复合变换

如果是对p(x, y)先平移(变换矩阵A), 然后旋转(变换矩阵B), 然后伸缩(变换矩阵C)呢?

p' =C(B(Ap)) ==>  p' = (CBA)p //矩阵乘法结合率

现在任意角度o的箭头就很简单了:

  1. 先把div旋转45度 成为 菱形, 变换为 M1
  2. 伸缩x轴, y轴 :
    x' = size * cos(o/2) = x * √2 *  cos(o/2)
    y' = size * sin(o/2) = y *  √2  * sin(o/2)

即: kx = √2 cos(o/2); ky = √2 sin(o/2)
这样就得到了任意角度的箭头。 变换为M2

如果箭头的方向不是指向右侧, 在进行一次旋转就可以得到任意方向的箭头。变换为M3

那么由于 p' =C(B(Ap)) ==> p' = (CBA)p, 我们就可以先计算出 M3M2M1,然后对div进行相应的变换,就可以得到任意角度, 任意方向的箭头了。

div的width和height就是箭头的边长, 通过调整可以获取任意边长的箭头。

React组件

为了方便使用, 这个箭头被封装为了一个 React组件。git地址

示例
简单箭头 模拟select 发散箭头
使用css实现任意大小,任意方向, 任意角度的箭头 使用css实现任意大小,任意方向, 任意角度的箭头 使用css实现任意大小,任意方向, 任意角度的箭头
props
name type default description
degree number 90 箭头的张角, 角度制
offsetDegree number 0 箭头的方向,默认指向右边
color string - 箭头的颜色
size string 10px 箭头边长
安装使用

npm install rc-arrow --save

import Arrow from 'rc-arrow'

class Hw extends Component {
    render() {
        return (
            <Arrow size="20px" color="red"/>
        )
    }
}

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
java反射, 不看你可别后悔
<divid"content\_views"class"markdown\_views"<!flowchart箭头图标勿删<svgxmlns"http://www.w3.org/2000/svg"style"display:none;"<pathstrokelinecap"round"d"M5,00,
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
AndroidStudio封装SDK的那些事
<divclass"markdown\_views"<!flowchart箭头图标勿删<svgxmlns"http://www.w3.org/2000/svg"style"display:none;"<pathstrokelinecap"round"d"M5,00,2.55,5z"id"raphael
Stella981 Stella981
3年前
Native memory allocation (mmap) failed to map xxx bytes for committing reserved memory
<divid"content\_views"class"markdown\_views"<!flowchart箭头图标勿删<svgxmlns"http://www.w3.org/2000/svg"style"display:none;"<pathstrokelinecap"round"d"M5,00,
Stella981 Stella981
3年前
Spring Boot 2下使用Feign找不到@EnableFeignClients的解决办法
<divid"content\_views"class"markdown\_views"<!flowchart箭头图标勿删<svgxmlns"http://www.w3.org/2000/svg"style"display:none;"<pathstrokelinecap"round"d"M5,00,2
Wesley13 Wesley13
3年前
Java8中的LocalDateTime工具类
<divid"content\_views"class"markdown\_views"<!flowchart箭头图标勿删<svgxmlns"http://www.w3.org/2000/svg"style"display:none;"<pathstrokelinecap"round"d"M5,00,
Wesley13 Wesley13
3年前
CSS常用样式(二):绘制双箭头
序言:总结一些常用CSS样式,方便以后使用目录一、多次调用单箭头二、旋转边框直接绘制双箭头一、多次调用单箭头上文介绍2种实现单箭头的方式:边框旋转、双三角覆盖。这次以边框旋转为例多次调用实现双箭头1、边框旋转单箭头实现.arrowright{
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
匿名网络
匿名网络
Lv1
红尘初妆,容我先开口,唱一出思君如流水。
文章
4
粉丝
0
获赞
0