当前位置:   article > 正文

在以太坊区块链上创建一个动态 SVG NFT_动态svg链

动态svg链

  通过Solidity编写的合约基于 ERC721 标准,并使用 OpenZeppelin 库来实现基本功能。

导入库

  1. import '@openzeppelin/contracts/token/ERC721/ERC721.sol';
  2. import '@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol';
  3. import '@openzeppelin/contracts/utils/Counters.sol';
  4. import 'base64-sol/base64.sol';
  5. import "@openzeppelin/contracts/utils/Strings.sol";

这些导入语句包含了 ERC721 标准合约、扩展功能、计数器工具、Base64 编码工具和字符串工具。

合约定义 

  1. contract DynamicSvgToken is ERC721URIStorage {
  2. using Counters for Counters.Counter;
  3. Counters.Counter private _tokenCounter;
  4. string[] palette;
  5. constructor() ERC721('Dynamic SVG Token', 'DST') {
  6. palette = ["blue", "red", "maroon", "black", "yellow", "orange", "purple", "gold", "lawngreen", "lightblue", "olive"];
  7. }
  8. function mint() external {
  9. _tokenCounter.increment();
  10. uint256 newTokenId = _tokenCounter.current();
  11. _safeMint(msg.sender, newTokenId);
  12. _setTokenURI(newTokenId, _constructTokenURI(newTokenId));
  13. }
  14. function _constructTokenURI(uint256 tokenId) internal view returns (string memory) {
  15. string memory svg = _constructSVG(tokenId);
  16. string memory json = Base64.encode(bytes(string(abi.encodePacked(
  17. '{"name": "',
  18. name(),
  19. '", "description": "A dynamic SVG NFT with animated gradient background", "image": "data:image/svg+xml;base64,',
  20. Base64.encode(bytes(svg)),
  21. '"}'
  22. ))));
  23. return string(abi.encodePacked('data:application/json;base64,', json));
  24. }
  25. function _constructSVG(uint256 tokenId) internal view returns (string memory) {
  26. uint seed = uint(keccak256(abi.encodePacked(block.timestamp, tokenId)));
  27. string memory gradientColors = _getRandomGradientColors(seed);
  28. string memory animationDuration = Strings.toString(5 + (seed % 10)); // 5-14 seconds
  29. return string(abi.encodePacked(
  30. "<svg width='500' height='500' xmlns='http://www.w3.org/2000/svg'>",
  31. "<defs>",
  32. "<linearGradient id='bg' x1='0%' y1='0%' x2='100%' y2='100%'>",
  33. gradientColors,
  34. "</linearGradient>",
  35. "</defs>",
  36. "<rect width='100%' height='100%' fill='url(#bg)'>",
  37. "<animate attributeName='x' from='-500' to='500' dur='", animationDuration, "s' repeatCount='indefinite'/>",
  38. "</rect>",
  39. _generateCircles(seed),
  40. "</svg>"
  41. ));
  42. }
  43. function _getRandomGradientColors(uint seed) internal view returns (string memory) {
  44. string memory color1 = palette[seed % palette.length];
  45. string memory color2 = palette[(seed / palette.length) % palette.length];
  46. string memory color3 = palette[(seed / (palette.length * palette.length)) % palette.length];
  47. return string(abi.encodePacked(
  48. "<stop offset='0%' stop-color='", color1, "'>",
  49. "<animate attributeName='stop-color' values='", color1, ";", color2, ";", color3, ";", color1, "' dur='10s' repeatCount='indefinite'/>",
  50. "</stop>",
  51. "<stop offset='100%' stop-color='", color2, "'>",
  52. "<animate attributeName='stop-color' values='", color2, ";", color3, ";", color1, ";", color2, "' dur='10s' repeatCount='indefinite'/>",
  53. "</stop>"
  54. ));
  55. }
  56. function _generateCircles(uint seed) internal pure returns (string memory) {
  57. string memory circles;
  58. for (uint i = 0; i < 3; i++) {
  59. uint circleSeed = uint(keccak256(abi.encodePacked(seed, i)));
  60. circles = string(abi.encodePacked(circles, _generateCircle(circleSeed, i)));
  61. }
  62. return circles;
  63. }
  64. function _generateCircle(uint seed, uint index) internal pure returns (string memory) {
  65. uint cx = seed % 400 + 50;
  66. uint cy = (seed / 1000) % 400 + 50;
  67. uint r = (seed / 1000000) % 50 + 10;
  68. string memory animationDuration = Strings.toString(3 + index * 2); // 3, 5, or 7 seconds
  69. return string(abi.encodePacked(
  70. "<circle cx='", Strings.toString(cx),
  71. "' cy='", Strings.toString(cy),
  72. "' r='", Strings.toString(r),
  73. "' fill='rgba(255,255,255,0.5)' stroke='white'>",
  74. "<animate attributeName='r' values='", Strings.toString(r), ";", Strings.toString(r + 10), ";", Strings.toString(r),
  75. "' dur='", animationDuration, "s' repeatCount='indefinite'/>",
  76. "</circle>"
  77. ));
  78. }
  79. }

定义了一个名为 DynamicSvgToken 的合约,继承自 ERC721URIStorage,并使用 Counters 库来管理代币 ID。palette 是一个包含颜色的字符串数组。构造函数初始化合约,设置代币名称为 "Dynamic SVG Token",符号为 "DST",并填充 palette 数组。mint 函数用于铸造新的代币,增加计数器并安全地将代币铸造给调用者,同时设置代币的 URI。_constructTokenURI 函数构建代币的 JSON 元数据,并将其编码为 Base64。_getRandomGradientColors 函数根据种子生成三个随机颜色,并创建渐变动画。_generateCircles 函数生成多个圆形元素,每个圆形都有不同的种子和动画。_generateCircle 函数生成一个带有动画的圆形元素。

总体来说,这段代码实现了一个动态生成 SVG 图像的 NFT,每个图像都有随机的渐变背景和动画圆形。

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/954654
推荐阅读
相关标签
  

闽ICP备14008679号