首页 > 解决方案 > 反应:将双色滑块拇指设置为具有透明背景的图像

问题描述

我做了一个滑块,左边应该是蓝色,右边是灰色。蓝色也应该比灰色更厚。

在此处输入图像描述

我有两个问题。

  1. 如果拇指块有一个透明的切口,则滑块的蓝色部分不会一直延伸到图像上可见的左侧。
  2. 我希望滑块的边缘是圆形的,尤其是蓝色边缘(我可能不需要灰色)

我的意思是圆形边缘在此处输入图像描述


这是代码的代码框

和代码本身

import React from "react";
import styled from "styled-components";
const image = "https://i.imgur.com/XMfYtkv.png";
const thumb = {
  width: 25,
  height: 26
};

const height = 36;
const trackHeight = 4;

// colours
const lowerBackground = `linear-gradient(to bottom, gray, gray) 100% 50% / 100% ${
  trackHeight / 2.5
}px no-repeat transparent`;
const upperBackground = `linear-gradient(to bottom, blue, blue) 100% 50% / 100% ${
  trackHeight / 2.5
}px no-repeat transparent`;

const makeLongShadow = (color, size) => {
  // Colors the slider to the right of the thumbpiece
  let i = 1;
  let shadow = `-${i}px 0 0 ${size} ${color}`;

  for (; i < 1950; i++) {
    //If i is a small number, like 720, then when the slider gets set to its minimum, the end of the slider is the color for the left side of the slider, when it should be the color for the right side
    shadow = `${shadow}, -${i}px 0 0 ${size} ${color}`;
  }

  return shadow;
};

const StyledSlider = styled.input`
  overflow: hidden;
  appearance: none;
  height: ${height}px;
  cursor: pointer;

  marginbottom: 0;

  &:focus {
    outline: none;
  }

  &::-webkit-slider-runnable-track {
    width: 100%;
    height: ${height}px;
    background: ${lowerBackground};
  }

  &::-webkit-slider-thumb {
    position: relative;
    appearance: none;
    height: ${thumb.height}px;
    width: ${thumb.width}px;
    background: url(${image});
    background-size: cover;
    border: 0;
    top: 50%;
    transform: translateY(-50%);
    box-shadow: ${makeLongShadow("blue", "-11px")};
    transition: background-color 150ms;
  }

  &::-moz-range-progress {
    background: ${lowerBackground};
  }

  &::-moz-range-track,
  &::-moz-range-progress {
    width: 100%;
    height: ${height};
    background: ${upperBackground};
  }

  &::-moz-range-thumb {
    appearance: none;
    margin: 0;
    height: ${thumb.height}px;
    width: ${thumb.height}px;
    background: url(${image});
    border: 0;
    transition: background-color 150ms;
  }

  &::-ms-track {
    width: 100%;
    height: ${height}px;
    border: 0;
    /* color needed to hide track marks */
    color: transparent;
    background: transparent;
  }

  &::-ms-fill-lower {
    background: ${lowerBackground};
  }

  &::-ms-fill-upper {
    background: ${upperBackground};
  }

  &::-ms-thumb {
    appearance: none;
    height: ${thumb.height}px;
    width: ${thumb.height}px;
    background: url(${image});
    border-radius: 100%;
    border: 0;
    transition: background-color 150ms;
    /* IE Edge thinks it can support -webkit prefixes */
    top: 0;
    margin: 0;
    box-shadow: none;
  }
`;

//!Black line is too thick when then margin at the bottom is 11 or 10 ? I don't know what would cause this
export default (props) => <StyledSlider type="range" {...props} />;

标签: javascriptcssreactjssliderstyled-components

解决方案


我注意到box-shadow重复导致性能下降,我修复了您的代码问题并改进了代码。在代码中,我写了一些注释来帮助你理解我做了什么。

import React from "react";
import ReactDOM from "react-dom";
import styled, { css } from "styled-components";

import "./styles.css";
const image = "https://i.imgur.com/XMfYtkv.png";

const thumbD = "50px"; // image width + height prefered same value

const filllC = "blue"; //first line
const trackC = "gray"; //second line
const trackH = "0.6em"; //dont change it if not neccessry
const firstFillthicker = 10; //in px
const secondFillthicker = 4; //in px

const track = css`
  box-sizing: border-box;
  border: none;
  height: ${secondFillthicker}px;
  background: ${trackC};
  border-radius: 8px;
`;

const trackFill = css`
  ${track};
  height: ${firstFillthicker}px;
  background-color: transparent;
  background-image: linear-gradient(${filllC}, ${filllC}),
    linear-gradient(${trackC}, ${trackC});
  background-size: var(--sx) ${firstFillthicker}px,
    calc(100% - var(--sx)) ${secondFillthicker}px;
  background-position: left center, right center;
  background-repeat: no-repeat;
`;
const inputCSS = css`
  width: 100%;
  --min: 0;
  --max: 100;
  --val: 50;
`;
const fill = css`
  height: ${trackH};
  background: ${filllC};
  border-radius: 4px;
`;

const thumb = css`
  margin-top: calc(0.5 * (${trackH} - ${thumbD}));
  cursor: pointer;
  margin-left: -15px;
  background-size: cover;
  background-color: transparent; // should add this for firefox
  background-image: url(${image});
  border: none;
  width: ${thumbD};
  height: ${thumbD};
`;

const StyledSlider = styled.input`
  &,
  &::-webkit-slider-thumb {
    -webkit-appearance: none;
  }

  &:focus {
    outline: none;
  }

  --range: calc(var(--max) - var(--min));
  --ratio: calc((var(--val) - var(--min)) / var(--range));
  --sx: calc(0.5 * ${thumbD} + var(--ratio) * (100% - ${thumbD}));

  margin: 0;
  padding: 0;
  height: ${thumbD};
  background: transparent;
  font: 1em/1 arial, sans-serif;

  &::-webkit-slider-runnable-track {
    ${trackFill};
  }

  &::-moz-range-track {
    ${track};
  }

  &::-ms-track {
    ${track};
  }

  &::-moz-range-progress {
    ${fill};
  }

  &::-ms-fill-lower {
    ${fill};
  }

  &::-webkit-slider-thumb {
    ${thumb};
  }

  &::-moz-range-thumb {
    ${thumb};
  }

  &::-ms-thumb {
    margin-top: 0;
    ${thumb};
  }

  &::-ms-tooltip {
    display: none;
  }

  &::-moz-focus-outer {
    border: 0;
  }
`;

export default (props) => <StyledSlider type="range" {...props} />;

确保传入 propsonInput函数,style就像这样

function Exam(){
  const [value, setValue] = React.useState(50);
   return (
    <App onInput={e => setValue(e.target.value)}
      style={{width: "80%","--min": 0,"--max": 100, "--val": value}} // pass the value from the props
     />
   )
}

这是一个活生生的例子

编辑滑块(样式化组件)(分叉)


推荐阅读