Filter.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import { getGradientFirstParam } from '.';
  2. import { Form, Switch } from 'antd';
  3. import hljs from 'highlight.js/lib/core';
  4. import React, { useState } from 'react';
  5. import shallow from 'zustand/shallow';
  6. import { symbols, rgbToString } from './Output';
  7. import { SectionTitle, SliderInput } from './subcomponents';
  8. import { useInputStore } from '~/components/store';
  9. export const FilterControls: React.FC = () => {
  10. const [svgProps, cssProps, filterProps, setFilterProps] = useInputStore(
  11. (state) => [state.svgProps, state.cssProps, state.filterProps, state.setFilterProps],
  12. shallow
  13. );
  14. const { contrast, brightness, invert } = filterProps;
  15. const [inlineSvg, setInlineSvg] = useState(false);
  16. const { size, baseFrequency, numOctaves } = svgProps;
  17. const { gradients } = cssProps;
  18. const gradientsString = gradients.map((grad) => {
  19. return `${grad.type}-gradient(${getGradientFirstParam(grad)}, ${rgbToString(
  20. grad.stops[0].color
  21. )}, ${rgbToString(grad.stops[1].color)})`;
  22. });
  23. const cleanSvgString = `<svg viewBox='0 0 ${size} ${size}' xmlns='http://www.w3.org/2000/svg'><filter id='noiseFilter'><feTurbulence type='fractalNoise' baseFrequency='${baseFrequency}' numOctaves='${numOctaves}' stitchTiles='stitch'/></filter><rect width='100%' height='100%' filter='url(#noiseFilter)'/></svg>`;
  24. const inlineSvgString = `url("data:image/svg+xml,${cleanSvgString.replace(
  25. symbols,
  26. encodeURIComponent
  27. )}")`;
  28. const resultCssDisplay = `/* resulting css */
  29. {
  30. width: 250px;
  31. height: 250px;
  32. background: ${gradientsString.join(', ')}, ${
  33. inlineSvg ? inlineSvgString : 'url(/👆/that/noise.svg)'
  34. };
  35. filter: contrast(${contrast}%) brightness(${brightness}%)${invert ? ' invert(100%)' : ''};
  36. }
  37. `;
  38. return (
  39. <div>
  40. <SectionTitle title="3. SVG + Gradient + CSSfilter" copyText={resultCssDisplay} />
  41. <pre className="hljs">
  42. <code
  43. dangerouslySetInnerHTML={{
  44. __html: hljs.highlight(resultCssDisplay, { language: 'css' }).value,
  45. }}
  46. />
  47. </pre>
  48. <Form>
  49. <SliderInput
  50. label="contrast"
  51. name="contrast"
  52. min={100}
  53. max={1000}
  54. step={10}
  55. tipFormatter={(v) => `${v}%`}
  56. onChange={(val: number) =>
  57. setFilterProps({
  58. ...filterProps,
  59. contrast: val,
  60. })
  61. }
  62. value={typeof contrast === 'number' ? contrast : 10}
  63. />
  64. <SliderInput
  65. label="brightness"
  66. name="brightness"
  67. min={100}
  68. max={1500}
  69. step={50}
  70. tipFormatter={(v) => `${v}%`}
  71. onChange={(val: number) =>
  72. setFilterProps({
  73. ...filterProps,
  74. brightness: val,
  75. })
  76. }
  77. value={typeof brightness === 'number' ? brightness : 0}
  78. />
  79. <Form.Item label="Invert">
  80. <Switch
  81. size="small"
  82. checked={invert}
  83. onChange={(v) =>
  84. setFilterProps({
  85. ...filterProps,
  86. invert: v,
  87. })
  88. }
  89. />
  90. </Form.Item>
  91. <Form.Item label="Inline the SVG">
  92. <Switch size="small" checked={inlineSvg} onChange={(e) => setInlineSvg(e)} />
  93. </Form.Item>
  94. </Form>
  95. </div>
  96. );
  97. };