更改光标样式时,光标属性被删除。

3
我正在查看这个库示例页面中的颜色选择器。我想要对它进行一些更改。在第210行的hsvDown函数中,有一行代码向hsv_map添加了no-cursor类,然后在第287行将其移除。
以下是.no-cursor的CSS样式:
.no-cursor .hsv-cursor, #hsv_map.no-cursor .cover {
    cursor: none;
}

我想仅使用JavaScript隐藏/显示光标,而不添加/删除class。因此,我尝试了以下操作:
JSFiddle中的第220行:
hsv_mapCover.style.cursor = hsv_mapCursor.style.cursor = 'none';

以下是 JSFiddle 中的第 270 行:

hsv_mapCover.style.cursor = hsv_mapCursor.style.cursor = 'crosshair';

当我运行代码时,光标总是在那里,不会消失。我在开发工具(在Chrome中按F12)中检查了一下,发现当您点击颜色选择器(colorWheel)时,.hsv-cursor 删除了cursor属性。然后,当您取消选择(mouseUp事件)时,cursor属性带有正确的十字线类型重新出现。
我不希望在单击颜色选择器时删除cursor属性。我想让cursornone
为什么在单击颜色选择器时会删除光标属性,以及如何在选择colorWheel时使cursor属性为none

JSFiddle

;(function(window, undefined) {
  "use strict"


  // Some common use variables
  var ColorPicker = window.ColorPicker,
    Tools = ColorPicker || window.Tools, // provides functions like addEvent, ... getOrigin, etc.
    colorSourceSelector = document.getElementById('description').getElementsByTagName('select')[0],
    startPoint,
    currentTarget,
    currentTargetWidth = 0,
    currentTargetHeight = 0;

  /* ---------------------------------- */
  /* ------- Render color patch ------- */
  /* ---------------------------------- */
  var testPatch = document.getElementById('testPatch'),
    renderTestPatch = function(color) { // used in renderCallback of 'new ColorPicker'
      var RGB = color.RND.rgb;

      testPatch.style.cssText =
        'background-color: rgba(' + RGB.r + ',' + RGB.g + ',' + RGB.b + ',' + color.alpha + ');' +
        'color: ' + (color.rgbaMixBlack.luminance > 0.22 ? '#222' : '#ddd');
      testPatch.firstChild.data = '#' + color.HEX;
    };

  /* ---------------------------------- */
  /* ------ Render contrast patch ----- */
  /* ---------------------------------- */
  var contrastPatch = document.getElementById('contrastPatch'),
    backGround = contrastPatch.firstChild,
    renderContrastPatch = function(color) { // used in renderCallback of 'new ColorPicker'
      var RGB = color.RND.rgb,
        bgColor = color.background.RGB,
        options = myColor.options ? myColor.options : myColor.color.options,
        cBGColor = myColor ? options.customBG : {},
        bgType,
        alphaBG;

      if (!cBGColor) {
        // contrastPatch.style.display = 'none';
        // return;
        cBGColor = {
          r: 1,
          g: 1,
          b: 1
        };
      }
      alphaBG = options.alphaBG;
      bgType = {
        w: 'White',
        b: 'Black',
        c: 'Custom'
      }[alphaBG];
      cBGColor = alphaBG === 'b' ? {
        r: 0,
        g: 0,
        b: 0
      } : alphaBG === 'w' ? {
        r: 1,
        g: 1,
        b: 1
      } : cBGColor;
      contrastPatch.style.cssText =
        'background-color: rgb(' +
        Math.round(cBGColor.r * 255) + ',' +
        Math.round(cBGColor.g * 255) + ',' +
        Math.round(cBGColor.b * 255) + ');' +
        'color: ' + 'rgba(' + RGB.r + ',' + RGB.g + ',' + RGB.b + ',' + color.alpha + ');';
      backGround.style.cssText =
        'background-color: rgba(' +
        bgColor.r + ',' +
        bgColor.g + ',' +
        bgColor.b + ',' + color.background.alpha + ');';
      contrastPatch.children[1].firstChild.data = color['rgbaMixBGMix' + bgType] ?
        '*' + color['rgbaMixBGMix' + bgType].WCAG2Ratio + '*' :
        '-Test-';
    };

  /* ---------------------------------- */
  /* ------- Render color values ------ */
  /* ---------------------------------- */
  var colorValues = document.getElementById('colorValues'),
    renderColorValues = function(color) { // used in renderCallback of 'new ColorPicker'
      var RND = color.RND;

      colorValues.firstChild.data =
        'rgba(' + RND.rgb.r + ',' + RND.rgb.g + ',' + RND.rgb.b + ',' + color.alpha + ')' + "\n" +
        'hsva(' + RND.hsv.h + ',' + RND.hsv.s + ',' + RND.hsv.v + ',' + color.alpha + ')' + "\n" +
        'hsla(' + RND.hsl.h + ',' + RND.hsl.s + ',' + RND.hsl.l + ',' + color.alpha + ')' + "\n" +
        'CMYK(' + RND.cmyk.c + ',' + RND.cmyk.m + ',' + RND.cmyk.y + ',' + RND.cmyk.k + ')' + "\n" +
        'CMY(' + RND.cmy.c + ',' + RND.cmy.m + ',' + RND.cmy.y + ')' + "\n" +
        'Lab(' + RND.Lab.L + ',' + RND.Lab.a + ',' + RND.Lab.b + ')'; // + "\n" +
    };

  /* ---------------------------------- */
  /* ---------- Color squares --------- */
  /* ---------------------------------- */
  var colorSquares = document.getElementById('color_squares'),
    squares = colorSquares.children,
    n = squares.length;

  for (; n--;) { // draw random color values as background
    squares[n].style.backgroundColor = 'rgb(' +
      Math.round(Math.random() * 255) + ',' +
      Math.round(Math.random() * 255) + ',' +
      Math.round(Math.random() * 255) + ')';
  }

  Tools.addEvent(colorSquares, 'click', function(e) { // event delegation
    var target = e.target || e.srcElement;

    if (target.parentNode === this) {
      myColor.setColor(target.style.backgroundColor);
      startRender(true);
    }
  });

  /* ---------------------------------- */
  /* ---------- Color sliders --------- */
  /* ---------------------------------- */
  var sliders = document.getElementById('sliders'),
    sliderChildren = sliders.children,
    type,
    mode,
    max = {
      rgb: {
        r: 255,
        g: 255,
        b: 255
      },
      hsl: {
        h: 360,
        s: 100,
        l: 100
      },
      cmy: {
        c: 100,
        m: 100,
        y: 100
      }
      // hsv:  {h: 360, s: 100, v: 100},
      // cmyk: {c: 100, m: 100, y: 100, k: 100},
    },
    sliderDown = function(e) { // mouseDown callback
      var target = e.target || e.srcElement,
        id, len;

      if (target !== this) {
        if (e.preventDefault) e.preventDefault();

        currentTarget = target.id ? target : target.parentNode;
        id = currentTarget.id; // rgbR
        len = id.length - 1;
        type = id.substr(0, len); // rgb
        mode = id.charAt(len).toLowerCase(); // R -> r
        startPoint = Tools.getOrigin(currentTarget);
        currentTargetWidth = currentTarget.offsetWidth;

        sliderMove(e);
        Tools.addEvent(window, 'mousemove', sliderMove);
        startRender();
      }
    },
    sliderMove = function(e) { // mouseMove callback
      var newColor = {};

      // The idea here is (so in the HSV-color-picker) that you don't
      // render anything here but just send data to the colorPicker, no matter
      // if it's out of range. colorPicker will take care of that and render it
      // then in the renderColorSliders correctly (called in renderCallback).
      newColor[mode] = (e.clientX - startPoint.left) / currentTargetWidth * max[type][mode];
      myColor.setColor(newColor, type);
    },
    renderColorSliders = function(color) { // used in renderCallback of 'new ColorPicker'
      for (var n = sliderChildren.length; n--;) {
        var child = sliderChildren[n],
          len = child.id.length - 1,
          type = child.id.substr(0, len),
          mode = child.id.charAt(len).toLowerCase();

        if (child.id) child.children[0].style.width = (color.RND[type][mode] / max[type][mode] * 100) + '%';
      }
    };

  Tools.addEvent(sliders, 'mousedown', sliderDown); // event delegation
  Tools.addEvent(window, 'mouseup', function() {
    Tools.removeEvent(window, 'mousemove', sliderMove);
    stopRender();
  });

  /* ---------------------------------- */
  /* ---- HSV-circle color picker ----- */
  /* ---------------------------------- */
  var hsv_map = document.getElementById('hsv_map'),
    hsv_mapCover = hsv_map.children[1], // well...
    hsv_mapCursor = hsv_map.children[2],
    hsv_barBGLayer = hsv_map.children[3],
    hsv_barWhiteLayer = hsv_map.children[4],
    hsv_barCursors = hsv_map.children[6],
    hsv_barCursorsCln = hsv_barCursors.className,
    hsv_Leftcursor = hsv_barCursors.children[0],
    hsv_Rightcursor = hsv_barCursors.children[1],

    colorDisc = document.getElementById('surface'),
    colorDiscRadius = colorDisc.offsetHeight / 2,
    luminanceBar = document.getElementById('luminanceBar'),

    hsvDown = function(e) { // mouseDown callback
      var target = e.target || e.srcElement;

      if (e.preventDefault) e.preventDefault();

      currentTarget = target.id ? target : target.parentNode;
      startPoint = Tools.getOrigin(currentTarget);
      currentTargetHeight = currentTarget.offsetHeight; // as diameter of circle

      Tools.addEvent(window, 'mousemove', hsvMove);
      hsv_mapCover.style.cursor = hsv_mapCursor.style.cursor = 'none';
      hsvMove(e);
      startRender();
    },
    hsvMove = function(e) { // mouseMove callback
      var r, x, y, h, s;

      if (currentTarget === hsv_map) { // the circle
        r = currentTargetHeight / 2,
          x = e.clientX - startPoint.left - r,
          y = e.clientY - startPoint.top - r,
          h = 360 - ((Math.atan2(y, x) * 180 / Math.PI) + (y < 0 ? 360 : 0)),
          s = (Math.sqrt((x * x) + (y * y)) / r) * 100;
        myColor.setColor({
          h: h,
          s: s
        }, 'hsv');
      } else if (currentTarget === hsv_barCursors) { // the luminanceBar
        myColor.setColor({
          v: (currentTargetHeight - (e.clientY - startPoint.top)) / currentTargetHeight * 100
        }, 'hsv');
      }
    },

    renderHSVPicker = function(color) { // used in renderCallback of 'new ColorPicker'
      var pi2 = Math.PI * 2,
        x = Math.cos(pi2 - color.hsv.h * pi2),
        y = Math.sin(pi2 - color.hsv.h * pi2),
        r = color.hsv.s * (colorDiscRadius - 5);

      hsv_mapCover.style.opacity = 1 - color.hsv.v;
      // this is the faster version...
      hsv_barWhiteLayer.style.opacity = 1 - color.hsv.s;
      hsv_barBGLayer.style.backgroundColor = 'rgb(' +
        color.hueRGB.r + ',' +
        color.hueRGB.g + ',' +
        color.hueRGB.b + ')';

      hsv_mapCursor.style.cssText =
        'left: ' + (x * r + colorDiscRadius) + 'px;' +
        'top: ' + (y * r + colorDiscRadius) + 'px;' +
        // maybe change className of hsv_map to change colors of all cursors...
        'border-color: ' + (color.RGBLuminance > 0.22 ? '#333;' : '#ddd');
      hsv_barCursors.className = color.RGBLuminance > 0.22 ? hsv_barCursorsCln + ' dark' : hsv_barCursorsCln;
      if (hsv_Leftcursor) hsv_Leftcursor.style.top = hsv_Rightcursor.style.top = ((1 - color.hsv.v) * colorDiscRadius * 2) + 'px';
    };

  Tools.addEvent(hsv_map, 'mousedown', hsvDown); // event delegation
  Tools.addEvent(window, 'mouseup', function() {
    Tools.removeEvent(window, 'mousemove', hsvMove);
    hsv_mapCover.style.cursor = hsv_mapCursor.style.cursor = 'crosshair';
    stopRender();
  });

  // generic function for drawing a canvas disc
  var drawDisk = function(ctx, coords, radius, steps, colorCallback) {
      var x = coords[0] || coords, // coordinate on x-axis
        y = coords[1] || coords, // coordinate on y-axis
        a = radius[0] || radius, // radius on x-axis
        b = radius[1] || radius, // radius on y-axis
        angle = 360,
        rotate = 0,
        coef = Math.PI / 180;

      ctx.save();
      ctx.translate(x - a, y - b);
      ctx.scale(a, b);

      steps = (angle / steps) || 360;

      for (; angle > 0; angle -= steps) {
        ctx.beginPath();
        if (steps !== 360) ctx.moveTo(1, 1); // stroke
        ctx.arc(1, 1, 1, (angle - (steps / 2) - 1) * coef, (angle + (steps / 2) + 1) * coef);

        if (colorCallback) {
          colorCallback(ctx, angle);
        } else {
          ctx.fillStyle = 'black';
          ctx.fill();
        }
      }
      ctx.restore();
    },
    drawCircle = function(ctx, coords, radius, color, width) { // uses drawDisk
      width = width || 1;
      radius = [
        (radius[0] || radius) - width / 2, (radius[1] || radius) - width / 2
      ];
      drawDisk(ctx, coords, radius, 1, function(ctx, angle) {
        ctx.restore();
        ctx.lineWidth = width;
        ctx.strokeStyle = color || '#000';
        ctx.stroke();
      });
    };

  if (colorDisc.getContext) {
    drawDisk( // HSV color wheel with white center
      colorDisc.getContext("2d"), [colorDisc.width / 2, colorDisc.height / 2], [colorDisc.width / 2 - 1, colorDisc.height / 2 - 1],
      360,
      function(ctx, angle) {
        var gradient = ctx.createRadialGradient(1, 1, 1, 1, 1, 0);
        gradient.addColorStop(0, 'hsl(' + (360 - angle + 0) + ', 100%, 50%)');
        gradient.addColorStop(1, "#FFFFFF");

        ctx.fillStyle = gradient;
        ctx.fill();
      }
    );
    drawCircle( // gray border
      colorDisc.getContext("2d"), [colorDisc.width / 2, colorDisc.height / 2], [colorDisc.width / 2, colorDisc.height / 2],
      '#555',
      3
    );
    // draw the luminanceBar bar
    var ctx = luminanceBar.getContext("2d"),
      gradient = ctx.createLinearGradient(0, 0, 0, 200);

    gradient.addColorStop(0, "transparent");
    gradient.addColorStop(1, "black");

    ctx.fillStyle = gradient;
    ctx.fillRect(0, 0, 30, 200);
  }


  /*
   * This script is set up so it runs either with ColorPicker or with Color only.
   * The difference here is that ColorPicker has a renderCallback that Color doesn't have
   * therefor we have to set a render intervall in case it's missing...
   * setInterval() can be exchanged to window.requestAnimationFrame(callBack)...
   *
   * If you want to render on mouseMove only then get rid of startRender(); in
   * all the mouseDown callbacks and add doRender(myColor.colors); in all
   * mouseMove callbacks. (Also remove all stopRender(); in mouseUp callbacks)
   */
  var doRender = function(color) {
      renderTestPatch(color);
      renderContrastPatch(color);
      renderColorValues(color);
      renderColorSliders(color);
      renderHSVPicker(color);
      // colorModel.innerHTML = displayModel(color); // experimental
    },
    renderTimer,
    // those functions are in case there is no ColorPicker but only Colors involved
    startRender = function(oneTime) {
      if (isColorPicker) { // ColorPicker present
        myColor.startRender(oneTime);
      } else if (oneTime) { // only Colors is instanciated
        doRender(myColor.colors);
      } else {
        renderTimer = window.setInterval(
          function() {
            doRender(myColor.colors);
            // https://dev59.com/JXA85IYBdhLWcg3wF_q0
          }, 13); // 1000 / 60); // ~16.666 -> 60Hz or 60fps
      }
    },
    stopRender = function() {
      if (isColorPicker) {
        myColor.stopRender();
      } else {
        window.clearInterval(renderTimer);
      }
    },
    renderCallback = doRender,
    // finally the instance of either ColorPicker or Colors (export for debugging purposes)
    color_ColorPicker = new(ColorPicker || Colors)({
      customBG: '#808080',
      imagePath: 'images/'
    }),
    color_Colors = new Colors(),
    myColor,
    isColorPicker = colorSourceSelector.value === 'ColorPicker';

  myColor = window.myColor = color_Colors;

  // in case ColorPicker is not there...
  if (!isColorPicker) { // initial rendering
    doRender(myColor.colors);
  }

  colorSourceSelector.onchange = function(e) {
    if (this.value === 'Colors') {
      color_ColorPicker.color.options.renderCallback = function(color) {};
      myColor = window.myColor = color_Colors;
      isColorPicker = false;
      doRender(myColor.colors);
    } else {
      color_ColorPicker.color.options.renderCallback = doRender;
      myColor = window.myColor = color_ColorPicker;
      isColorPicker = true;
      doRender(myColor.color.colors);
    }
  }


  function conversionTest(skipDisplay) {
    if (skipDisplay) console.time('convertAll');

    // conversion test
    var convert = myColor.color ? myColor.color.convertColor : myColor.convertColor,
      x = 0.85,
      y = 0.33,
      z = 0.23,
      k = 0.1,
      modes = ['hsl', 'hsv', 'rgb', 'cmy', 'cmyk', 'Lab', 'XYZ', 'HEX'],
      color = {},
      fromMode = '',
      toMode = '',
      counter = 0,
      value,
      colorOut = [],
      valueOut = [],
      isLab = false;

    for (var o = 2; o--;) {
      for (var n = 0, m = modes.length; n < m; n++) {
        if (modes[n] === 'HEX') {
          color = '89ABCD';
        } else {
          color = {};
          isLab = modes[n] === 'Lab';
          color[modes[n][0]] = o && !isLab ? x : Math.round(x * 100) + (isLab ? x : 0);
          color[modes[n][1]] = o && !isLab ? y : Math.round(y * 100) + (isLab ? y : 0);
          color[modes[n][2]] = o && !isLab ? z : Math.round(z * 100) + (isLab ? z : 0);
          if (modes[n] === 'cmyk') {
            color[modes[n][3]] = o ? k : Math.round(k * 100);;
          }
        }
        fromMode = o ? modes[n] : modes[n].toUpperCase();
        for (var d = 2; d--;) {
          for (var p = 0, q = modes.length; p < q; p++) {
            toMode = d ? modes[p] : modes[p].toUpperCase();
            if (fromMode !== toMode) { // && fromMode !== 'LAB' && toMode !== 'LAB') {
              if ((!d && /(?:XYZ|HEX)/.test(toMode)) || // good to avoid double 2XYZ or 2HEX
                (!o && /(?:XYZ|HEX)/.test(fromMode))) { // good to avoid double XYZ2 or HEX2
                // do nothing
              } else {
                value = convert(color, fromMode + '2' + toMode);
                if (!skipDisplay) {
                  colorOut = [];
                  for (var s in color) {
                    colorOut.push(s + ': ' + color[s]);
                  }
                  colorOut = fromMode === 'HEX' ? '"' + color + '"' : '{' + colorOut.join(', ') + '}';

                  valueOut = [];
                  for (var s in value) {
                    valueOut.push(s + ': ' + value[s]);
                  }
                  valueOut = toMode === 'HEX' ? '"' + value + '"' : '{' + valueOut.join(', ') + '}';

                  console.log('convertColor(' + colorOut + ', "' + fromMode +
                    '2' + toMode + '") = ' + valueOut);
                }
                counter++;
              }
            }
          }
        }
      }
    }
    console.log('Tested ' + counter + ' conversion combinations (excluding same to same)');
    if (!skipDisplay) console.log('Call conversionTest(true) for timer (incl. calculations in for loops though...)');
    if (skipDisplay) console.timeEnd('convertAll');
  }

  window.conversionTest = conversionTest;

  // conversionTest();

})(window);
.cp-app {
  display: none;
}
<link href="https://rawgit.com/PitPik/colorPicker/master/index.css" rel="stylesheet" />

<div id="testPatch">.</div>

<div id="contrastPatch">
  <div></div><i>-Test-</i>
</div>

<div id="colorValues">.</div>

<div id="sliders" class="sliders">
  <div id="rgbR">
    <div></div>
  </div>
  <div id="rgbG">
    <div></div>
  </div>
  <div id="rgbB">
    <div></div>
  </div>

  <div id="hslH">
    <div></div>
  </div>
  <div id="hslS">
    <div></div>
  </div>
  <div id="hslL">
    <div></div>
  </div>

  <!-- <div id="cmyC"><div></div></div>
  <div id="cmyM"><div></div></div>
  <div id="cmyY"><div></div></div> -->
</div>

<div id="hsv_map">
  <canvas id="surface" width="200" height="200"></canvas>
  <div class="cover"></div>
  <div class="hsv-cursor"></div>
  <div class="bar-bg"></div>
  <div class="bar-white"></div>
  <canvas id="luminanceBar" width="25" height="200"></canvas>
  <div class="hsv-barcursors" id="hsv_cursors">
    <div class="hsv-barcursor-l"></div>
    <div class="hsv-barcursor-r"></div>
  </div>
</div>

<div id="color_squares">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

<div id="description">Demo patches: demonstrate how to build color pickers and how Colors' / ColorPicker's API work. Patches are linked to
  <select>
    <option value="Colors">Colors</option>
    <option value="ColorPicker">ColorPicker</option>
  </select>
  <p>See a simple jQuery implementation <a href="jQuery_implementation/">preview here</a> or a simple javaScript implementation <a href="javaScript_implementation/">preview here</a>
  </p>
</div>

<script type="text/javascript" src="https://rawgit.com/PitPik/colorPicker/master/colors.js"></script>
<script type="text/javascript" src="https://rawgit.com/PitPik/colorPicker/master/colorPicker.data.js"></script>
<script type="text/javascript" src="https://rawgit.com/PitPik/colorPicker/master/colorPicker.js"></script>
<script type="text/javascript" src="index.js"></script>


我认为在 hsv_mapCover.style.cursor = hsv_mapCursor.style.cursor = 'none'; 下面两行的 startRender() 会将光标返回。如果你将其注释掉,你可能会得到你想要的行为。也许你应该关闭该函数触发的某些操作。 - Nikolay Ermakov
谢谢您的评论!startRender()基本上调用了doRender,而doRender又调用了一整套其他函数。请问您能告诉我您所指的行号,或者给我发送一个更新(修复)后的JSFiddle吗? - Horay
1个回答

2
问题出现在 renderHSVPicker 函数内的 第275-277行,当光标渲染时,.cssText 属性被设置。
hsv_mapCursor.style.cssText =
    'left: ' + (x * r + colorDiscRadius) + 'px;' + 
    'top: ' + (y * r + colorDiscRadius) + 'px;' +
    // ...

这个CSS覆盖了你在回调函数中设置的光标样式。

简单的解决方法是在设置这些属性时将cursor设置为none

更新示例

hsv_mapCursor.style.cssText =
    'left: ' + (x * r + colorDiscRadius) + 'px;' +
    'top: ' + (y * r + colorDiscRadius) + 'px;' +
    'cursor: none;' +
    // ...

mousedown/mouseup 回调函数中,您仍需要设置封面元素的 cursor 属性:

// In the mousedown callback (line 220):

Tools.addEvent(window, 'mousemove', hsvMove);
hsv_mapCover.style.cursor = 'none';

// In the mouseup callback (line 271):

Tools.addEvent(window, 'mouseup', function() {
  Tools.removeEvent(window, 'mousemove', hsvMove);
  hsv_mapCover.style.cursor = '';
  stopRender();
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接