正经地图,数一数二的实用艺术

※ 编码思路 来源于CreateJs官方Project
地图来源 自然资源部地图技术审查中心承办的标准地图服务网站 《中国地势图 1:1600万 8开》 审图号:GS(2016)1609号
想要了解和下载更多关于 标准地图 的内容,欢迎访问中国地图出版集团官网和中国地图出版集团官方微博

文章目录

  • 效果展示
  • 代码分释
  • 全部代码

效果展示






代码分释

整体思路

通过调整定义在Bitmap层的Filter参数,来调整图层的亮度、对比度、饱和度、色调以及模糊等属性。而参数值,通过拖动“滑块”的方式获取。“滑块”则是自定义扩展的Slider Shape

显示元素

  • map 背景地图
  • panel 半透明的控制面板区域
  • texts & sliders 6个滑块以及对应的文本

0 加载资源 & 创建舞台

stage = new createjs.Stage('examCanvas')
image = new Image()
image.onload = handleImageLoad
image.src = '../_assets/img/cmap_ground.png'

1 map 元素

map = new createjs.Bitmap(image)
map.cache(0, 0, 960, 400)

colorMatrix = new createjs.ColorMatrix()
colorMatrixFilter = new createjs.ColorMatrixFilter(colorMatrix)
blurFilter = new createjs.BlurFilter(0, 0, 2)

map.filters = [colorMatrixFilter, blurFilter]

stage.addChild(map)

其中 colorMatrixblurFilter 是后续所需调节参数的滤镜

2 panel 元素

panel = new createjs.Shape(
    new createjs.Graphics().beginFill('rgba(0,0,0,0.5)').drawRect(760, 0, 200, 400)
)
stage.addChild(panel)

3 定义 Slider

// Slider.js
(function () {
     
    /**
     * 定义滑块shape类
     * @param {最小值} min 
     * @param {最大值} max 
     * @param {元素宽度} width 
     * @param {元素高度} height 
     */
    function Slider(min, max, width, height) {
     
        this.Shape_constructor()

        this.min = this.value = min || 0
        this.max = max || 100
        this.width = width || 100
        this.height = height || 20

        this.values = {
     }

        this.trackColor = '#eee'
        this.thumbColor = '#666'

        this.cursor = 'pointer'

        this.on('mousedown', this._handleInput, this)
        this.on('pressmove', this._handleInput, this)
    }

    let p = createjs.extend(Slider, createjs.Shape)

    p.isVisible = function () {
      return true }

    p.draw = function (ctx, ignoreCache) {
     
        if (this._checkChange()) {
     
            let x = (this.width - this.height) * Math.min(1, Math.max(0, (this.value - this.min) / (this.max - this.min)))
            this.graphics.clear()
                .beginFill(this.trackColor).drawRect(0, 0, this.width, this.height)
                .beginFill(this.thumbColor).drawRect(x, 0, this.height, this.height)
        }

        this.Shape_draw(ctx, true)
    }

    p._checkChange = function () {
     
        if (this.values.value != this.value) {
     
            this.values.value = this.value
            return true
        }
        return false
    }

    /**
     * 处理滑块上的鼠标事件
     * @param {触发事件对象} evt 
     */
    p._handleInput = function (evt) {
     
        let val = (evt.localX - this.height / 2) / (this.width - this.height) * (this.max - this.min) + this.min
        val = Math.max(Math.min(val, this.max), this.min)

        if (this.value == val) {
     
            return
        }

        this.value = val
        this.dispatchEvent('change')
    }
    
    window.Slider = createjs.promote(Slider, 'Shape')
})()

构建 Slider 超类,并将其父类指向 Shape,同时定义 mousedown & pressmove 事件来获取滑块当前的值,并触发change事件。通过 draw 方法,在 Shape_draw 之前,绘制“滑轨”和“滑块”

extend(subclass, superclass)
为新类设置原型链和构造函数属性。创建类构造函数后应立即调用此方法

  • subclass 子类
  • superclass 扩展的超类

promote(subclass prefix)
使可以通过prefix_方法名的格式,调用父类的相关方法,例如代码中的 Shape_constructorShape_draw。在完全定义了类的原型之后,应调用此方法

  • subclass 子类
  • prefix 前缀。通常是超类的名称

isVisible()
返回true或false,指示在绘制到画布上时Shape是否可见

draw(ctx, [ignoreCache=false])
将显示对象绘制到指定的上下文中,而忽略其可见,alpha,阴影和变换

  • ctx 要绘制的画布2D上下文对象
  • ignoreCache 指示绘图操作是否应忽略任何当前缓存

dispatchEvent(eventObj, [bubbles], [cancelable])
触发事件
eventObj 事件或事件字符串

4 创建 Sliders & Text 元素

let names = ['亮度', '对比度', '饱和度', '色调', '水平模糊', '垂直模糊']
let labels = ['brightness', 'contrast', 'saturation', 'hue', 'blurX', 'blurY']
for (let i = 0; i < labels.length; i++) {
     
    let n = names[i]
    let l = labels[i]

    let x = 780
    let y = i * 60 + 20
    let val = i < 4 ? 0.5 : 0

    sliders[l] = SliderItem(n, x, y, val)
}

循环创建 text & slider 元素

// 创建单组text & slider 元素
function SliderItem(name, x, y, val = 0) {
     
    let label = new createjs.Text(name, '18px 微软雅黑', '#fff').set({
      x, y })
    let slider = new Slider(0, 1, 160, 20).set({
      x, y: y + 25 })
    slider.value = val

    slider.on("change", handleSliderChange, this);
    stage.addChild(label, slider)
    return slider
}

// 当滑块滑动时,处理change事件,调整map的滤镜值
function handleSliderChange() {
     
    blurFilter.blurX = sliders.blurX.value * 10;
    blurFilter.blurY = sliders.blurY.value * 10;

    colorMatrix.setColor(
        sliders.brightness.value * 200 - 100,
        sliders.contrast.value * 200 - 100,
        sliders.saturation.value * 200 - 100,
        sliders.hue.value * 360 - 180);

    map.updateCache();
    stage.update();
}

全部代码

Github - FilterInput


<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Filters Inputtitle>
    <link rel="stylesheet" href="../_assets/css/shared.css">
    <script src="../_assets/js/shared.js">script>
    <script src="../lib/easeljs-NEXT.js">script>
    <script src="./Slider.js">script>

    <script>
        let image
        let map, panel
        let colorMatrix, blurFilter
        let sliders = {
      }

        function Init() {
      
            shared.loading()

            stage = new createjs.Stage('examCanvas')

            image = new Image()
            image.onload = handleImageLoad
            image.src = '../_assets/img/cmap_ground.png'
        }

        function handleImageLoad() {
      
            shared.loaded()

            stage.enableMouseOver()            
            stage.mouseMoveOutside = true

            map = new createjs.Bitmap(image)
            map.cache(0, 0, 960, 400)

            colorMatrix = new createjs.ColorMatrix()
            colorMatrixFilter = new createjs.ColorMatrixFilter(colorMatrix)
            blurFilter = new createjs.BlurFilter(0, 0, 2)

            map.filters = [colorMatrixFilter, blurFilter]

            stage.addChild(map)

            panel = new createjs.Shape(
                new createjs.Graphics().beginFill('rgba(0,0,0,0.5)').drawRect(760, 0, 200, 400)
            )

            stage.addChild(panel)

            let names = ['亮度', '对比度', '饱和度', '色调', '水平模糊', '垂直模糊']
            let labels = ['brightness', 'contrast', 'saturation', 'hue', 'blurX', 'blurY']
            for (let i = 0; i < labels.length; i++) {
      
                let n = names[i]
                let l = labels[i]

                let x = 780
                let y = i * 60 + 20
                let val = i < 4 ? 0.5 : 0

                sliders[l] = SliderItem(n, x, y, val)
            }

            stage.update()
        }

        function SliderItem(name, x, y, val = 0) {
      
            let label = new createjs.Text(name, '18px 微软雅黑', '#fff').set({
       x, y })
            let slider = new Slider(0, 1, 160, 20).set({
       x, y: y + 25 })
            slider.value = val

            slider.on("change", handleSliderChange, this);

            stage.addChild(label, slider)

            return slider
        }

        function handleSliderChange() {
      
            blurFilter.blurX = sliders.blurX.value * 10;
            blurFilter.blurY = sliders.blurY.value * 10;

            colorMatrix.setColor(
                sliders.brightness.value * 200 - 100,
                sliders.contrast.value * 200 - 100,
                sliders.saturation.value * 200 - 100,
                sliders.hue.value * 360 - 180);

            map.updateCache();
            stage.update();
        }

    script>
head>

<body onload="Init()">
    <header class="Nora7aki">
        <h1>滤镜Filtersh1>

        <p>
            自定义 <code>Slidercode> 类,继承于 <code>Shapecode>,对其进行操作,从而调整 <code>mapcode> 层的
            <code>ColorMatrixFiltercode><code>BlurFiltercode>
        p>
    header>

    <div>
        <canvas id="examCanvas" width="960" height="400">canvas>
    div>
body>

html>

欢迎关注微信公众号 "书咖里的曼基康"
正经地图,数一数二的实用艺术_第1张图片

你可能感兴趣的:(CreateJs,js,canvas)