使用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')

则有:

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 发散箭头

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"/>
)
}
}

使用css实现任意大小,任意方向, 任意角度的箭头的更多相关文章

  1. PHP图像裁剪为任意大小的图像,图像不变形,不留下空白

    <?php /** * 说明:函数功能是把一个图像裁剪为任意大小的图像,图像不变形 * 参数说明:输入 需要处理图片的 文件名,生成新图片的保存文件名,生成新图片的宽,生成新图片的高 */ fu ...

  2. linux c使用socket进行http 通信,并接收任意大小的http响应(三)

    使用socket进行http通信的时候,浏览器返回的响应经常不是固定长度的,有时候很大,有些时候又非常小,十分讨厌.如果仅仅只是为了接收一小段信息,设置一个十分大的缓存,这样又会十分浪费.而且经常更改 ...

  3. linux shell 脚本攻略学习10--生成任意大小的文件和文本文件的交集与差集详解

    一.生成任意大小的文件(dd命令): 举例: amosli@amosli-pc:~/learn/example$ ; + records in + records out bytes ( MB/s a ...

  4. oracle 产生一个任意大小的随机数

    SELECT DBMS_RANDOM.RANDOM FROM DUAL;          产生一个任意大小的随机数 SELECT ABS(MOD(DBMS_RANDOM.RANDOM,100)) F ...

  5. 用python生成你想要的任意大小文件

    在测试的日常工作中,我们经常会需要测试上传文件的边界值.今天分享一段30行的简单代码,可以生成任意大小的文件,方便测试. file_size=input("请输入想要生成文件的大小:(单位M ...

  6. 通过 NewLife.XCode 迁移任意现有数据库到任意数据库

    通过 NewLife.XCode 迁移任意现有数据库到任意数据库(附分表分库方法) 本文背景是将其他系统的数据库迁移到另一个数据库(仅需 20 行代码),也可以作为项目迁移用,生成自己系统的专属实体代 ...

  7. js 获取任意一个元素的任意一个样式属性的值

    //谷歌,火狐支持console.log(window.getComputedStyle(my$("dv"),null).left);//IE8支持console.log(my$( ...

  8. hdu5795 A Simple Nim 求nim求法,打表找sg值规律 给定n堆石子,每堆有若干石子,两个人轮流操作,每次操作可以选择任意一堆取走任意个石子(不可以为空) 或者选择一堆,把它分成三堆,每堆不为空。求先手必胜,还是后手必胜。

    /** 题目:A Simple Nim 链接:http://acm.hdu.edu.cn/showproblem.php?pid=5795 题意:给定n堆石子,每堆有若干石子,两个人轮流操作,每次操作 ...

  9. Pop–实现任意iOS对象的任意属性的动态变化

    简介 Pop 是一个可扩展的动画引擎,可用于实现任意iOS对象的任意属性的动态变化,支持一般动画,弹性动画和渐变动画三种类型. 项目主页: pop 最新示例: 点击下载 注意: 官方代码中,并不包含实 ...

随机推荐

  1. spring项目获取ApplicationContext(能手动从Spring获取所需要的bean)

    最流行的方法就是  实现ApplicationContextAware接口 @Component public class SpringContextUtil implements Applicati ...

  2. (转载)虚拟化(3):os调度策略。

    转自:https://zhuanlan.zhihu.com/p/38046313 这一章主要是介绍几个简单的调度器策略.内容比较简单,就简单汇总下. 首先我们对现有的计算机环境有如下几个假设: 1.每 ...

  3. 四、Java基础

    Java基础 在开始学习Java基础之前,我们先来学习一下IDEA 打开IDEA,新建一个项目(New Project),选择空项目(Empty Project),填写项目名(Project name ...

  4. 彩色建模(四色原型) Object Modeling in Color学习心得

    定义4种类的原型,在UML中用不同颜色表示不同原型的对象     1. Party, Place, Thing Party: 事件的参与方,例如某人人.某组织等 Place: 事件的发生地,例如仓库. ...

  5. laravel 返回统一的json数据

    laravel 在Api接口开发中,可以使用 response()->json(["code"=>200,"msg"=>"ok&qu ...

  6. Java入土---基本DOS命令

    基本DOS命令 打开cmd方式 开始+系统+命令提示符 win+R,输入cmd 在任意文件夹下,按住shift + 右键,打开命令行窗口 资源管理器里打开 常用DOS命令 盘符切换 E: dir命令查 ...

  7. tensorflow编译成功!

    使用bazel编译tensorflow项目的core包成功!找了个简单的target可视化,留作纪念,命令如下: bazel query --noimplicit_deps --nohost_deps ...

  8. BBS项目分布搭建二(个人站点相关)

    BBS项目分布搭建二 1. 首页详情补充 # 在home.html文件中 body标签内补充: <div class="container-fluid"> <di ...

  9. 使用vscode Container开发调试envoy

    由于我最近在研究 envoy 这个项目,这是个cpp的项目,对于我这种cpp新人来说还是比较有压力的,感觉处处都是坑,开个引导文章记录一下. 如果要研究 envoy 项目源码,那肯定是需要代码跳转的, ...

  10. ArcMap进行天空开阔度(SVF)分析

    这里的SVF并不是生物学或医学的(Stromal Vascular Fraction),而是指GIS中的(Sky View Factor,SVF),即为(城市)天空开阔度. 城市天空开阔度(Sky V ...