• 【自己给自己题目做】之一:椭圆可点击区域


    【题一】
    请实现以下需求,要做一个活动页面,页面上有一张图片(假设是800x600),图片正中心有一个椭圆形的可点击区域,假设椭圆长轴为200px(横向),短轴160px(纵向),请实现点击这个椭圆区域弹出“我被点击了”的字样,而其他区域点击无效。(不一定要兼容低端浏览器,能兼容当然更好)

    我说这是我曾经出过的一道笔试题。其实主要考察点是基本的数学能力和用web前端相关知识实现需求的综合能力。难度不算太大。用普通的dom或者canvas来实现都ok,因为其实重要思路是一致的。椭圆区域还是要自己判断。

    先看demo后讲思路:

    demo: http://hongru.github.io/quiz/1/index.html

    考点主要是以下几个:

    1. 常用dom操作和简单事件机制(用类库比如jq也算)
    2. 简单数学知识(椭圆公式,坐标是否在椭圆区域的判断)
    3. 数学模型到编程实践的简单转换

    代码不复杂:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8" />
    <style>
    body{
        font-family:Microsoft Yahei;
    }
    .doc {
        width: 804px;
        margin: 0 auto;
    }
    #cont {
        border: 2px solid #999;
        height: 600px;
        position: relative;
    }
    .dot {
        position: absolute;
        width:1px;
        height: 1px;
        overflow: hidden;
        font-size:0;
        line-height: 0;
        background: #333;
    }
    </style>
    </head>
    
    <body>
        <div class="doc">
        <h4>【题一】</h4>
        <p>
    请实现以下需求,要做一个活动页面,页面上有一张图片(假设是800x600),图片正中心有一个椭圆形的可点击区域,假设椭圆长轴为200px(横向),短轴160px(纵向),请实现点击这个椭圆区域弹出“我被点击了”的字样,而其他区域点击无效。(不一定要兼容低端浏览器,能兼容当然更好)</p>
    
            <div id="cont"></div>
        </div>
        
        <script>
            ;(function () {
                var win = window,
                    doc = document,
                    OFFSET;
                    
                function _bind (el, ev, fn) {
                    return el.addEventListener ? el.addEventListener(ev, fn, false) : el.attachEvent('on'+ev, function () { fn.call(el); });
                }
                function _$ (id) {
                    return doc.getElementById(id) || id;
                }                               
                
                function _drawElipse (id, a, b) {
                    var el = _$(id);
                    var docfrag = doc.createDocumentFragment();
                    for (var i = 0; i < 360; i ++) {
                        var dot = doc.createElement('div');
                        dot.className = 'dot';
                        
                        var l = a*Math.sin(i) + (el.offsetWidth - 4)/2,
                            t = b*Math.cos(i) + (el.offsetHeight - 4)/2;
                        
                        dot.style.left = l + 'px';
                        dot.style.top = t + 'px';
                        
                        docfrag.appendChild(dot);
                    }
                    el.appendChild(docfrag);
                }
                
                function offset (el) {
                     var width = el.offsetWidth,
                        height = el.offsetHeight,
                        top = el.offsetTop,
                        left = el.offsetLeft;
                    while (el = el.offsetParent) {
                        top = top + el.offsetTop;
                        left = left + el.offsetLeft;
                    }
    
                    return {
                        top: top,
                        left: left,
                        height: height,
                         width
                    }
                }
                
                function clickCheck (e) {
                    e = e || win.event;
                    var tar = e.target || e.srcElement,
                        x = e.clientX + doc.body.scrollLeft + doc.documentElement.scrollLeft - OFFSET.left - (tar.offsetWidth/2),
                        y = e.clientY + doc.body.scrollTop + doc.documentElement.scrollTop - OFFSET.top - (tar.offsetHeight/2);
                    
                    var r = Math.pow((x/100), 2) + Math.pow((y/80), 2);
                    console && console.log(x, y, r);
                    if (r < 1) {
                        alert('椭圆被点击了!');
                    }
                }
                
                function __init() {
                    _drawElipse('cont', 100, 80);
                    
                    var el = _$('cont');
                    OFFSET = offset(el);
                    _bind(el, 'click', clickCheck);
                }
                __init();
            })();
        </script>
    </body>
    </html>
    View Code

    其实重要的代码就是以下一段:

     1         function clickCheck (e) {
     2                 e = e || win.event;
     3                 var tar = e.target || e.srcElement,
     4                     x = e.clientX + doc.body.scrollLeft + doc.documentElement.scrollLeft - OFFSET.left - (tar.offsetWidth/2),
     5                     y = e.clientY + doc.body.scrollTop + doc.documentElement.scrollTop - OFFSET.top - (tar.offsetHeight/2);
     6                 
     7                 var r = Math.pow((x/100), 2) + Math.pow((y/80), 2);
     8                 console && console.log(x, y, r);
     9                 if (r < 1) {
    10                     alert('椭圆被点击了!');
    11                 }
    12             }    

    因为椭圆是画在中心的,上面的4,5行,获取x,y其实就是获取当前鼠标位置相对于容器中心的相对距离。(要算上scroll的距离和容器本身距离页面边缘的位置)

    然后用椭圆公式,如果这个值小于1,那么表示在椭圆内点击的。

    结束。

    -------------------------------------

    下期:定宽容器内若干大小不定图片自动排列的问题,允许一定程度内的缩放和裁剪,类似于下面的结果:

  • 相关阅读:
    cf D. Vessels
    cf C. Hamburgers
    zoj 3758 Singles' Day
    zoj 3777 Problem Arrangement
    zoj 3778 Talented Chef
    hdu 5087 Revenge of LIS II
    zoj 3785 What day is that day?
    zoj 3787 Access System
    判断给定图是否存在合法拓扑排序
    树-堆结构练习——合并果子之哈夫曼树
  • 原文地址:https://www.cnblogs.com/hongru/p/3187934.html
Copyright © 2020-2023  润新知