echarts扇形模拟镜头焦距与可视化角度示意图

关于镜头焦距的概念,是光学系统中衡量光的聚集或发散的度量方式,指平行光入射时从透镜光心到光聚集之焦点的距离 。具有短焦距的光学系统比长焦距的光学系统有更佳聚集光的能力。简单的说焦距是焦点到面镜的中心点之间的距离。

# 实例图

<iframe style="border: 0;overflow: auto" width="100%" height="550px" 
        src="https://www.tuu14.com/gallery/focal-length-angle-of-view-guide" scrolling="no"></iframe>
Show Copy

# 绘制

# 准备数据

我们准备好数据,已整理为对象数组的形式,name是焦距,angle是可视角度,color是为了区分定义的不同颜色

const data = [
    {name: '鱼眼', angle: 180, color: 'rgba(136,171,255,0.99)'},
    {name: '14mm', angle: 114, color: 'rgba(141,185,255,0.88)'},
    {name: '20mm', angle: 94, color: 'rgba(144,196,249,0.99)'},
    {name: '24mm', angle: 84, color: 'rgba(135,217,251,0.95)'},
    {name: '28mm', angle: 75, color: 'rgba(140,222,221,0.94)'},
    {name: '35mm', angle: 63, color: 'rgba(141,230,183,0.96)'},
    {name: '50mm', angle: 46, color: 'rgba(139,239,137,0.91)'},
    {name: '70mm', angle: 34, color: 'rgba(181,248,136,0.91)'},
    {name: '80mm', angle: 30, color: 'rgba(226,253,121,0.94)'},
    {name: '85mm', angle: 28, color: 'rgba(226,253,121,0.93)'},
    {name: '100mm', angle: 24, color: 'rgba(251,219,137,0.94)'},
    {name: '135mm', angle: 18, color: 'rgba(253,180,137,0.94)'},
    {name: '200mm', angle: 12, color: 'rgba(255,139,135,0.96)'},
    {name: '300mm', angle: 8, color: 'rgba(253,139,203,0.94)'},
    {name: '400mm', angle: 6, color: 'rgba(238,140,247,0.97)'},
    {name: '500mm', angle: 5, color: 'rgba(192,162,235,0.94)'},
    {name: '600mm', angle: 4, color: 'rgba(138,170,255,0.96)'},
    {name: '800mm', angle: 3, color: 'rgba(138,170,255,0.96)'},
    {name: '1200mm', angle: 2, color: 'rgba(138,170,255,0.96)'},
]

# 绘制思路

我们选用echarts来绘制,简单来讲就是绘制多个扇形叠加在一起。

echarts 没有直接绘制扇形的类型,我们可以用饼图来模拟,动态计算每个饼图的角度,在将其余部分设置为透明色即可

const series = data.map(({name, color, angle}, idx) => {
    return {
        name: '可视角度',
        type: 'pie',
        radius: (13 * (data.length - idx + 1)) + '%', // 这里是每个扇形半径的步进百分比
        startAngle: 90 + angle / 2, // 起始角度,为了中心对称,所以需要angle除以2 
        center: ['50%', '100%'], // 整个图形摆放的位置,由于是扇形,透明下半部分就不用显示在图中了 
        data: [ // data分为两部分,扇形部分即是我们要展示的,另外缺口用透明色填充模拟扇形
            {
                value: angle, 
                name,
                itemStyle: {
                    color,
                    opacity: 0.6,
                    borderType: "solid",
                    borderWidth: 2,
                    borderColor: "rgba(255, 255, 255, 1)",
                }
            },
            {
                value: 360 - angle,
                name: '',
                labelLine: {show: false},
                label: {show: false},
                itemStyle: {
                    color: 'transparent'
                }
            }
        ],
    }
})

# 完整代码

const data = [
    {name: '鱼眼', angle: 180, color: 'rgba(136,171,255,0.99)'},
    {name: '14mm', angle: 114, color: 'rgba(141,185,255,0.88)'},
    {name: '20mm', angle: 94, color: 'rgba(144,196,249,0.99)'},
    {name: '24mm', angle: 84, color: 'rgba(135,217,251,0.95)'},
    {name: '28mm', angle: 75, color: 'rgba(140,222,221,0.94)'},
    {name: '35mm', angle: 63, color: 'rgba(141,230,183,0.96)'},
    {name: '50mm', angle: 46, color: 'rgba(139,239,137,0.91)'},
    {name: '70mm', angle: 34, color: 'rgba(181,248,136,0.91)'},
    {name: '80mm', angle: 30, color: 'rgba(226,253,121,0.94)'},
    {name: '85mm', angle: 28, color: 'rgba(226,253,121,0.93)'},
    {name: '100mm', angle: 24, color: 'rgba(251,219,137,0.94)'},
    {name: '135mm', angle: 18, color: 'rgba(253,180,137,0.94)'},
    {name: '200mm', angle: 12, color: 'rgba(255,139,135,0.96)'},
    {name: '300mm', angle: 8, color: 'rgba(253,139,203,0.94)'},
    {name: '400mm', angle: 6, color: 'rgba(238,140,247,0.97)'},
    {name: '500mm', angle: 5, color: 'rgba(192,162,235,0.94)'},
    {name: '600mm', angle: 4, color: 'rgba(138,170,255,0.96)'},
    {name: '800mm', angle: 3, color: 'rgba(138,170,255,0.96)'},
    {name: '1200mm', angle: 2, color: 'rgba(138,170,255,0.96)'},
].reverse()
const series = data.map(({name, color, angle}, idx) => {
    return {
        name: '可视角度',
        type: 'pie',
        radius: (13 * (data.length - idx + 1)) + '%',
        startAngle: 90 + angle / 2,
        label: {
            alignTo: 'edge',
            formatter: '{b} - {c}度',
            minMargin: 5,
            edgeDistance: 10,
            lineHeight: 10,
        },
        labelLine: {
            length: 0,
            length2: 0,
            maxSurfaceAngle: 80
        },
        labelLayout: function (params) {
            const isLeft = true
            const points = params.labelLinePoints;
            points[2][0] = isLeft
                ? params.labelRect.x
                : params.labelRect.x + params.labelRect.width;
            return {
                labelLinePoints: points
            };
        },
        center: ['50%', '100%'],
        data: [
            {
                value: angle, name,
                itemStyle: {
                    color,
                    opacity: 0.6,
                    borderType: "solid",
                    borderWidth: 2,
                    borderColor: "rgba(255, 255, 255, 1)",
                }
            },
            {
                value: 360 - angle,
                name: '',
                labelLine: {show: false},
                label: {show: false},
                itemStyle: {
                    color: 'transparent'
                }
            }
        ],
        emphasis: {
            itemStyle: {
                shadowBlur: 10,
                shadowOffsetX: 0,
                shadowColor: 'rgba(0, 0, 0, 0.5)'
            }
        }
    }
})

export const opt = {
    title: {
        text: '镜头焦距与可视角度的关系',
        left: 'center',
        textStyle: {
            color: '#252323',
            fontWeight: 'normal',
            fontSize: 18
        }
    },
    tooltip: {
        trigger: 'axis',
        axisPointer: {
            type: 'shadow'
        }
    },
    series
}

# 相关资料

最近更新
01
vite插件钩子
03-02
02
vite的依赖预构建
02-13
03
vite-基于ESM的下一代构建工具
02-10
更多文章>