为什么绝对定位指示符会超出相对定位的容器?

时间:2018-12-27 14:06:20

标签: javascript css css-position colorbox color-picker

我设计了一个颜色选择器,从中可以在画布旁边显示所选的颜色。现在的问题是,即使位置相对,我每次尝试将指示器拖出画布时,也是如此。

每次我尝试将指示器拖出画布时。我在下图中高亮显示了指示器

Every time i am trying to drag the indicator it goes out of canvas. I have highlighted the indicator in the image below

var canvas = document.getElementById('color-picker');
        var context = canvas.getContext('2d');
        var w = 250;
        var h = 250;

        canvas.width = w;
        canvas.height = h;

        var x = canvas.width / 2;
        var y = canvas.height / 2;
        var radius = x;


        for (var angle = 0; angle <= 360; angle += 1) {
            var startAngle = (angle - 2) * Math.PI / 180;
            var endAngle = angle * Math.PI / 180;

            context.beginPath();
            context.moveTo(x, y);
            context.arc(x, y, radius, startAngle, endAngle, false);
            context.closePath();

            var gradient = context.createRadialGradient(x, y, 0, x, y, radius);
            gradient.addColorStop(0, 'hsl(' + angle + ', 10%, 100%)');
            gradient.addColorStop(1, 'hsl(' + angle + ', 100%, 50%)');

            context.fillStyle = gradient;
            context.fill();
        }


        var m = {
            x: canvas.width / 2,
            y: canvas.height / 2
        };

        var drag = false;

        var location_path = document.getElementById('_lp_');
        var lp_width = location_path.offsetWidth;
        var lp_height = location_path.offsetHeight;

        var container = document.getElementById('container');
        var selected_color = document.getElementById('selected_color');

        var def_color = "#f8fff9";

        selected_color.style.backgroundColor = def_color;

        container.addEventListener('mousedown', dragged, false);
        container.addEventListener('mousemove', moving, false);
        window.addEventListener('mouseup', noDrag, false);


        function dragged() {
            drag = true;
        }
        function noDrag() {
            drag = false;
        }
        function moving(e) {
            if (drag) {
                var ink_x = (e.clientX - container.offsetLeft);
                var ink_y = (e.clientY - container.offsetTop);
                m.x = e.clientX - container.offsetLeft - lp_width / 2;
                m.y = e.clientY - container.offsetTop - lp_height - 10; //why 10? 10 for padding

                if (Distance(ink_x, ink_y, w / 2, h / 2) > radius) {
                    drag = false;
                }


                location_path.style.left = m.x + 'px';
                location_path.style.top = m.y + 'px';

                var getData = context.getImageData(ink_x, ink_y, 1, 1);
                var pxl = getData.data;

                var r = pxl[0];
                var g = pxl[1];
                var b = pxl[2];
                var a = pxl[3];

                // indicator.style.background = "rgb(" + r + ',' + g + ',' + b + ")";
                selected_color.style.background = "rgb(" + r + ',' + g + ',' + b + ")";
            }
        }




        function rgb2hex(red, green, blue) {
            var rgb = blue | (green << 8) | (red << 16);
            return '#' + (0x1000000 + rgb).toString(16).slice(1)
        }
        function Distance(x1, y1, x2, y2) {
            var dx = x2 - x1;
            var dy = y2 - y1;
            return Math.sqrt(dx * dx + dy * dy);
        }
.lighting-wrapper {
            margin: 5% auto;
        }

        .lighting-left,
        .lighting-right {
            padding: 50px;
        }

        .lighting-color-picker-wrapper,
        .lighting-selected-color-wrapper {
            position: relative;
            width: 250px;
            height: 250px;
            margin: 150px auto;
            border-radius: 50%;
        }

        .location-path {
            position: absolute;
            width: 40px;
            height: 40px;
            padding: 10px;
            background: #fff;
            border-radius: 50%;
            border-bottom-left-radius: 0%;
            top: 58px;
            left: 92px;
            transform: rotate(-45deg);
            box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
            user-select: none;
            transition: all 0.1s;
        }
<div class="container">
        <div class="lighting-wrapper shadow-sm">
            <div class="row align-items-center">
                <div class="col-md-6 d-flex justify-content-center lighting-left">
                    <div class="lighting-color-picker-wrapper" id="container">
                        <canvas id="color-picker" class="position-relative"></canvas>
                        <div id="_lp_" class="location-path"></div>
                    </div>
                </div>
                <div class="col-md-6 d-flex justify-content-center lighting-right">
                    <div class="lighting-selected-color-wrapper" id="selected_color">

                    </div>
                </div>
            </div>
        </div>
    </div>

1 个答案:

答案 0 :(得分:0)

看起来您的代码受页面滚动的影响。

尝试将“ e.clientY”更改为“ e.pageY”。

var canvas = document.getElementById('color-picker');
        var context = canvas.getContext('2d');
        var w = 250;
        var h = 250;

        canvas.width = w;
        canvas.height = h;

        var x = canvas.width / 2;
        var y = canvas.height / 2;
        var radius = x;


        for (var angle = 0; angle <= 360; angle += 1) {
            var startAngle = (angle - 2) * Math.PI / 180;
            var endAngle = angle * Math.PI / 180;

            context.beginPath();
            context.moveTo(x, y);
            context.arc(x, y, radius, startAngle, endAngle, false);
            context.closePath();

            var gradient = context.createRadialGradient(x, y, 0, x, y, radius);
            gradient.addColorStop(0, 'hsl(' + angle + ', 10%, 100%)');
            gradient.addColorStop(1, 'hsl(' + angle + ', 100%, 50%)');

            context.fillStyle = gradient;
            context.fill();
        }


        var m = {
            x: canvas.width / 2,
            y: canvas.height / 2
        };

        var drag = false;

        var location_path = document.getElementById('_lp_');
        var lp_width = location_path.offsetWidth;
        var lp_height = location_path.offsetHeight;

        var container = document.getElementById('container');
        var selected_color = document.getElementById('selected_color');

        var def_color = "#f8fff9";

        selected_color.style.backgroundColor = def_color;

        container.addEventListener('mousedown', dragged, false);
        container.addEventListener('mousemove', moving, false);
        window.addEventListener('mouseup', noDrag, false);


        function dragged() {
            drag = true;
        }
        function noDrag() {
            drag = false;
        }
        function moving(e) {
            if (drag) {
                var ink_x = (e.pageX - container.offsetLeft);
                var ink_y = (e.pageY - container.offsetTop);

                if (Distance(ink_x, ink_y, w / 2, h / 2) > radius) {
                    var vector = { x: ink_x - w / 2, y: ink_y - h / 2 };
                    normalize(vector);
                    ink_x = Math.trunc(vector.x * radius) + w / 2;
                    ink_y = Math.trunc(vector.y * radius) + h / 2;
                    drag = false;
                }

                m.x = ink_x - lp_width / 2;
                m.y = ink_y - lp_height - 10; //why 10? 10 for padding

                location_path.style.left = m.x + 'px';
                location_path.style.top = m.y + 'px';

                var getData = context.getImageData(ink_x, ink_y, 1, 1);
                var pxl = getData.data;

                var r = pxl[0];
                var g = pxl[1];
                var b = pxl[2];
                var a = pxl[3];

                // indicator.style.background = "rgb(" + r + ',' + g + ',' + b + ")";
                selected_color.style.background = "rgb(" + r + ',' + g + ',' + b + ")";
            }
        }




        function rgb2hex(red, green, blue) {
            var rgb = blue | (green << 8) | (red << 16);
            return '#' + (0x1000000 + rgb).toString(16).slice(1)
        }
        function Distance(x1, y1, x2, y2) {
            var dx = x2 - x1;
            var dy = y2 - y1;
            return Math.sqrt(dx * dx + dy * dy);
        }
        function normalize(vector) {
            var length = Math.sqrt(Math.pow(vector.x, 2) + Math.pow(vector.y, 2));
            vector.x = vector.x / length;
            vector.y = vector.y / length;
        }
.lighting-wrapper {
            margin: 5% auto;
        }

        .lighting-left,
        .lighting-right {
            padding: 50px;
        }

        .lighting-color-picker-wrapper,
        .lighting-selected-color-wrapper {
            position: relative;
            width: 250px;
            height: 250px;
            margin: 150px auto;
            border-radius: 50%;
        }

        .location-path {
            position: absolute;
            width: 40px;
            height: 40px;
            padding: 10px;
            background: #fff;
            border-radius: 50%;
            border-bottom-left-radius: 0%;
            top: 58px;
            left: 92px;
            transform: rotate(-45deg);
            box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
            user-select: none;
            transition: all 0.1s;
        }
<div class="container">
        <div class="lighting-wrapper shadow-sm">
            <div class="row align-items-center">
                <div class="col-md-6 d-flex justify-content-center lighting-left">
                    <div class="lighting-color-picker-wrapper" id="container">
                        <canvas id="color-picker" class="position-relative"></canvas>
                        <div id="_lp_" class="location-path"></div>
                    </div>
                </div>
                <div class="col-md-6 d-flex justify-content-center lighting-right">
                    <div class="lighting-selected-color-wrapper" id="selected_color">

                    </div>
                </div>
            </div>
        </div>
    </div>