使用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. Git教学教程--学生使用教程(非Git操作版)

    一.注册(必须) 注册完成后由"教师"将你加入高校/企业组即可: 二.查看项目(必须) 三.查看组织 打开后可查看到如下界面,列出的项目为可操作项目 四.查看高校/企业信息 五.上 ...

  2. LeetCode-010-正则表达式匹配

    正则表达式匹配 题目描述:给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配. '.' 匹配任意单个字符 '*' 匹配零个或多个前面的那一个元素 所谓匹配 ...

  3. Redis环境搭建-Linux单机

    一.准备Linux 可以买云服务器,也可以用虚拟机,我用的是虚拟机Oracle VM VirtualBox 二.编译环境 1.检查linux下是否安装环境 yum list installed | g ...

  4. CS61b proj1a

    得分46.25有一个点的bug不会修(希望大佬带我),style没有注意.1.LinkedListDeque.java public class LinkedListDeque <T>{ ...

  5. 【行业Tip】两化融合

    工业4.0 智能制造规划 两化融合是信息化和工业化的高层次的深度结合, 是指以信息化带动工业化.以工业化促进信息化,走新型工业化道路:两化融合的核心就是信息化支撑,追求可持续发展模式.

  6. promise 理解与总结

    对Promise的理解 Promise是异步编程的一种解决方案,可以获取异步操作的消息,避免了地狱回调,它比传统的解决方案回调函数和事件更合理和更强大. 所谓Promise,简单说就是一个容器,里面保 ...

  7. LGP5161口胡

    大家好,我是后缀自动机套线段树魔怔人,我非常喜欢使用后缀自动机套线段树草字符串题. 看到一个区间加上一个相同的数后等于另外一个区间,很容易想到先对序列做差分,统计长度为1的答案后再来统计这些. 直接统 ...

  8. OpenTracing 简介

    自从 Google Dapper 的论文发布之后,各大互联网公司和开源社区开发的分布式链路追踪产品百花齐放,同时也给使用者带来了一个问题,各个分布式链路追踪产品的 API 并不兼容,如果用户在各个产品 ...

  9. 安全学习笔记-web安全之XSS攻击

    web安全之XSS攻击 XSS 即跨站脚本攻击,是 OWASP TOP10 之一.它的全称为 Cross-site scripting,因为 CSS 这个简称已经被占用表示为前端三剑客之一的CSS,所 ...

  10. 获取bing首页的每日一图

    从必应(bing)首页抓取他的每日一图 以前上学时,曾经用python写过一个每天抓取bing每日一图的小工具. 现在想用java来重构一下. 抓取图片的思路 首先获取网页源码 从网页源码中,我们可以 ...