我有一个色轮选择器(我从该库中获取了大量代码)。我正在尝试使色轮光标不超出范围。我不希望它通过灰色边框。
我可以做明显的,使家长div
:overflow:hidden
,但这只是隐藏光标,就不会让它不去通过边界。
我认为要编辑的相关变量是以下内容之一(在hsvMove
函数中,从第39行开始):
var r = currentTargetHeight / 2,
x = e.pageX - startPoint.left - r,
y = e.pageY - startPoint.top - r
如何使光标不越过边界?
(function(window) {
"use strict"
// Some common use variables
var myColor = new Colors(),
startPoint,
currentTarget,
currentTargetHeight = 0,
PI = Math.PI,
PI2 = PI * 2;
/* ---------------------------------- */
/* ---- HSV-circle color picker ----- */
/* ---------------------------------- */
var colorDiskWrapper = document.getElementById('colorDiskWrapper'),
colorDiskCursor = document.getElementById('colorDiskCursor'),
colorDisk = document.getElementById('colorDisk');
var colorDiscRadius = colorDisk.offsetHeight / 2;
// Create Event Functions
var hsvDown = function(e) { // mouseDown callback
var target = e.target || e.srcElement;
if (e.preventDefault) e.preventDefault();
if (target === colorDiskCursor || target === colorDisk) {
currentTarget = target.parentNode;
} else
return;
startPoint = getOrigin(currentTarget);
currentTargetHeight = currentTarget.offsetHeight;
addEvent(window, 'mousemove', hsvMove);
hsvMove(e);
startRender();
},
hsvMove = function(e) { // mouseMove callback
var r = currentTargetHeight / 2,
x = e.pageX - startPoint.left - r,
y = e.pageY - startPoint.top - r,
h = 360 - ((Math.atan2(y, x) * 180 / PI) + (y < 0 ? 360 : 0)),
s = (Math.sqrt((x * x) + (y * y)) / r) * 100;
myColor.setColor({
h: h,
s: s
}, 'hsv');
},
renderHSVPicker = function(color) { // used in renderCallback of 'new ColorPicker'
var x = Math.cos(PI2 - color.hsv.h * PI2),
y = Math.sin(PI2 - color.hsv.h * PI2),
r = color.hsv.s * colorDiscRadius;
// Position the Cursor
colorDiskCursor.style.left = (x * r + colorDiscRadius) + 'px';
colorDiskCursor.style.top = (y * r + colorDiscRadius) + 'px';
};
addEvent(colorDiskWrapper, 'mousedown', hsvDown); // event delegation
addEvent(window, 'mouseup', function() {
removeEvent(window, 'mousemove', hsvMove);
stopRender();
});
var doRender = function(color) {
renderHSVPicker(color);
},
renderTimer,
startRender = function(oneTime) {
if (oneTime) { // only Colors is instanciated
doRender(myColor.colors);
} else {
renderTimer = window.setInterval(
function() {
doRender(myColor.colors);
// http://stackoverflow.com/questions/2940054/
}, 13); // 1000 / 60); // ~16.666 -> 60Hz or 60fps
}
},
stopRender = function() {
window.clearInterval(renderTimer);
};
/*
Function Helpers
*/
function getOrigin(elm) {
var box = (elm.getBoundingClientRect) ? elm.getBoundingClientRect() : {
top: 0,
left: 0
},
doc = elm && elm.ownerDocument,
body = doc.body,
win = doc.defaultView || doc.parentWindow || window,
docElem = doc.documentElement || body.parentNode,
clientTop = docElem.clientTop || body.clientTop || 0, // border on html or body or both
clientLeft = docElem.clientLeft || body.clientLeft || 0;
return {
left: box.left + (win.pageXOffset || docElem.scrollLeft) - clientLeft,
top: box.top + (win.pageYOffset || docElem.scrollTop) - clientTop
};
}
function addEvent(obj, type, func) {
addEvent.cache = addEvent.cache || {
_get: function(obj, type, func, checkOnly) {
var cache = addEvent.cache[type] || [];
for (var n = cache.length; n--;) {
if (obj === cache[n].obj && '' + func === '' + cache[n].func) {
func = cache[n].func;
if (!checkOnly) {
cache[n] = cache[n].obj = cache[n].func = null;
cache.splice(n, 1);
}
return func;
}
}
},
_set: function(obj, type, func) {
var cache = addEvent.cache[type] = addEvent.cache[type] || [];
if (addEvent.cache._get(obj, type, func, true)) {
return true;
} else {
cache.push({
func: func,
obj: obj
});
}
}
};
if (!func.name && addEvent.cache._set(obj, type, func) || typeof func !== 'function') {
return;
}
if (obj.addEventListener) obj.addEventListener(type, func, false);
else obj.attachEvent('on' + type, func);
}
function removeEvent(obj, type, func) {
if (typeof func !== 'function') return;
if (!func.name) {
func = addEvent.cache._get(obj, type, func) || func;
}
if (obj.removeEventListener) obj.removeEventListener(type, func, false);
else obj.detachEvent('on' + type, func);
}
})(window);
#colorDisk {
background-image: url("http://i.imgur.com/tX5NbWs.png");
width: 350px;
height: 350px;
background-repeat: no-repeat;
cursor: pointer;
}
#colorDiskCursor {
position: absolute;
border: 2px solid black;
border-radius: 50%;
width: 9px;
height: 9px;
cursor: pointer;
}
<div id="colorDiskWrapper">
<div id="colorDisk"></div>
<div id="colorDiskCursor"></div>
</div>
<script src="https://rawgit.com/PitPik/colorPicker/master/colors.js"></script>
问题:
让我们从概述算法开始,这样我们就知道我们要做什么:每次移动/单击鼠标,计算鼠标相对于(HSV彩色系统的)色盘的位置所表示的H
和S
值。定期在H
与和S
值对应的位置上准确呈现磁盘光标。
我们需要注意以下几点:
我们应该用来计算颜色值的实际半径(S
特别是)是色盘的半径减去光标的半径,因为我们要防止光标离开色盘的边界。在这种情况下,我们有175px
- 6.5px
,即168.5px
。
渲染光标时,我们将其设置为左上角。我们需要将位置偏移其半径,以使“手指指针”很好地出现在光标的中间。
解:
基于以上理解,解决方案很简单。
由于使用的是彩色磁盘的整个半径(175px
),而没有考虑磁盘光标的半径(),因此代码存在问题6.5px
。
您还应该在代码中修复/考虑的几件事:
您currentTargetHeight
是包装纸(350px
)的高度,然后将其减半以得出r
。这对我来说似乎是错误的。您完全不必担心包装器的尺寸。从代码中删除此变量。我们需要关注的价值应该是colorDiskRadius
和colorDiskCursorRadius
。
您colorDiscCursor
的设置为position: absolute
,但是它的偏移父级不是包装器,因为包装器不是定位的元素。因此,我们为其设置的左上角位置colorDiscCursor
可能完全不可预测,这取决于其实际父级在实际页面上的位置。要解决此问题,请将wrapper设置为position: relative
。
我注意到您没有设置box-sizing
(默认为content-box
),这就是为什么13px
尽管有width: 9px
;但光标实际上仍然很宽的原因。同样的高度。我个人喜欢使用它,box-sizing: border-box
这样当我必须进行像素精确的计算时,我只需要查看CSS中的realwidth
和height
属性,而不必同时参考padding
and border
。
次要问题:您disc
有时disk
在代码中使用和。为了理智起见,请尝试对此进行标准化。
TL; DR
这是实现1、2和4的小提琴:https : //jsfiddle.net/hrnn9w9k/4/
我没有包括3,因为它可能不是您的首选,但我强烈建议您使用。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句