继续告诉值为null

时间:2018-04-23 19:09:05

标签: javascript html css null

这是我的代码:

var Ribbon = /** @class */ (function () {
    function Ribbon(svg) {
        this.rootPos = Math.random() * 100;
        this.states = {
            start: {
                type: 'start',
                start: { thickness: 0, top: 60, left: 0 },
                end: { thickness: 0, top: 60, left: 100 },
                wave: { amplitude: 0, frequency: 0.008, transitionSpeed: 0.5 }
            },
            home: {
                type: 'home',
                start: { thickness: 30, top: 50, left: 0 },
                end: { thickness: 15, top: 60, left: 100 },
                wave: { amplitude: 40, frequency: 0.015, transitionSpeed: -0.5 }
            },
            selected: {
                type: 'selected',
                start: { thickness: 15, top: 80, left: 0 },
                end: { thickness: 24, top: 25, left: 100 },
                wave: { amplitude: 50, frequency: 0.004, transitionSpeed: 0.5 }
            }
        };
        this.size = { svg: { width: window.innerWidth, height: window.innerHeight } };
        this.currentState = JSON.parse(JSON.stringify(this.states.start));
        this.rows = 3;
        this.lines = [];
        this.blocks = [];
        this.defaultRestSpeed = 0.009;
        this.speed = {
            changeState: 2,
            rest: 1
        };
        this.waveLineAttr = {
            fill: 'none',
            stroke: 'white',
            strokeWidth: 1
        };
        this.svg = svg;
    }
    Ribbon.prototype.init = function () {
        var _this = this;
        this.blocks = [
            {
                type: 'menu',
                id: '1',
                title: 'Products',
                position: { current: 105, target: 5, home: 5 },
                width: 20,
                row: 2
            },
            {
                type: 'menu',
                id: '2',
                title: 'Blog',
                position: { current: 137, target: 37, home: 37 },
                width: 10,
                row: 3
            },
            {
                type: 'menu',
                title: 'About Us',
                id: '3',
                position: { current: 147, target: 47, home: 47 },
                width: 20,
                row: 1
            },
            {
                type: 'menu',
                id: '4',
                title: 'Contact',
                position: { current: 175, target: 75, home: 75 },
                width: 15,
                row: 2
            },
            {
                type: 'back',
                id: 'back',
                title: '<-- Back',
                position: { current: -100, target: -100, home: -100 },
                width: 10,
                row: 1
            }
        ];
        this.ribbon = this.svg.polygon().attr({
            fill: 'red',
            stroke: 'none'
        });
        // this.topWaveGuideLine = this.svg.path().attr(this.waveLineAttr);
        // this.bottomWaveGuideLine = this.svg.path().attr(this.waveLineAttr);
        this.resizeSVG();
        this.tick(0);
        this.updateRibbon();
        setTimeout(function () {
            _this.setState(_this.states.home);
        }, 1000);
    };
    Ribbon.prototype.updateRibbon = function () {
        var _this = this;
        var freq = this.currentState.wave.frequency;
        var pos = this.rootPos;
        var amp = this.currentState.wave.amplitude;
        var x1 = (this.size.svg.width / 100) * this.currentState.start.left;
        var y1 = ((this.size.svg.height / 100) * this.currentState.start.top);
        var x2 = (this.size.svg.width / 100) * this.currentState.end.left;
        var y2 = (this.size.svg.height / 100) * this.currentState.end.top;
        var t1 = ((this.size.svg.height / 100) * this.currentState.start.thickness) / 2;
        var t2 = ((this.size.svg.height / 100) * this.currentState.end.thickness) / 2;
        this.guidePath = this.getGuidePath(freq, pos, amp, x1, y1, x2, y2);
        var topPathPoints = this.getPathOffset(this.guidePath, -t1, -t2);
        this.paths = [topPathPoints];
        if (this.rows > 1) {
            var startHeightSpace = ((this.size.svg.height / 100) * this.currentState.start.thickness);
            var endHeightSpace = ((this.size.svg.height / 100) * this.currentState.end.thickness);
            for (var i_1 = 1; i_1 < this.rows; i_1++) {
                var startOffset = (0 - (startHeightSpace / 2)) + ((startHeightSpace / this.rows) * i_1);
                var endOffset = (0 - (endHeightSpace / 2)) + ((endHeightSpace / this.rows) * i_1);
                var path = this.getPathOffset(this.guidePath, startOffset, endOffset);
                this.paths.push(path);
                if (!this.lines[i_1 - 1])
                    this.lines.push(this.svg.path().attr(this.waveLineAttr));
                this.lines[i_1 - 1].attr({ d: this.getWavePathString(path) });
            }
        }
        var bottomPath = this.getPathOffset(this.guidePath, t1, t2);
        this.paths.push(bottomPath);
        this.ribbon.attr({ points: this.getWavePolygon(topPathPoints, bottomPath.slice(0).reverse()) });
        for (var i = 0; i < this.blocks.length; i++) {
            var block = this.blocks[i];
            var startX = (this.size.svg.width / 100) * block.position.current;
            var endX = (this.size.svg.width / 100) * (block.position.current + block.width);
            if (startX > this.size.svg.width)
                startX = this.size.svg.width;
            else if (startX < 0)
                startX = 0;
            if (endX > this.size.svg.width)
                endX = this.size.svg.width;
            else if (endX < 0)
                endX = 0;
            var path1 = this.paths[block.row - 1];
            var path2 = this.paths[block.row];
            var chunk1 = path1.slice(startX, endX);
            var chunk2 = path2.slice(startX, endX);
            if (chunk1.length > 1 && chunk2.length > 1) {
                var textPaddingX = 20;
                var textPaddingY = 10;
                var fontSize = this.getBlockFontSize(chunk1, chunk2, textPaddingY);
                var boxPolyPoints = this.getWavePolygon(chunk1, chunk2.reverse());
                if (!block.svg) {
                    block.svg = {};
                    block.svg.group = this.svg.group().attr({ "class": 'block', id: block.id });
                    block.svg.group.click(function (e) { _this.onBlockClick(e); });
                    block.svg.box = block.svg.group.polygon().attr({ fill: 'white', stroke: 'none' });
                    block.svg.mask = this.svg.polygon().attr({ fill: 'white', stroke: 'none' }).toDefs();
                    block.svg.textpath = block.svg.group.path().attr({ fill: 'none', stroke: 'white' }).toDefs();
                    block.svg.text = block.svg.group.text(0, 0, block.title).attr({ textpath: block.svg.textpath, mask: block.svg.mask });
                }
                block.svg.box.attr({ points: boxPolyPoints });
                block.svg.mask.attr({ points: boxPolyPoints });
                block.svg.text.attr({ fontSize: fontSize });
                if (endX - startX > textPaddingX * 2) {
                    var newPath = this.getPathOffset(path2.slice(startX + textPaddingX, endX - textPaddingX), -textPaddingY, -textPaddingY);
                    if (newPath.length > 2) {
                        var newPathString = this.getWavePathString(newPath);
                        block.svg.textpath.attr({ d: newPathString });
                    }
                }
            }
            else {
                if (block.svg) {
                    block.svg.group.remove();
                    block.svg.mask.remove();
                    block.svg = null;
                }
            }
        }
    };
    Ribbon.prototype.getGuidePath = function (freq, pos, amp, x1, y1, x2, y2) {
        var points = [];
        var width = x2 - x1;
        var x = x1;
        var y = y1;
        var yChange = y2 - y1;
        while (x++ <= width) {
            y = Math.sin(x * freq + pos);
            points.push([x, (y1 + ((width - (width - x)) * (yChange / width)) + (y * amp / 2 + amp / 2))]);
        }
        return points;
    };
    Ribbon.prototype.getPathOffset = function (points, offsetStart, offsetEnd) {
        if (points.length) {
            var x1 = points[0][0];
            var y1 = points[0][1];
            var x2 = points[points.length - 1][0];
            var y2 = points[points.length - 1][1];
            var yChange = offsetStart - offsetEnd;
            var width = x1 - x2;
            var newPoints = [];
            for (var i = 0; i < points.length; i++) {
                var newPoint = [points[i][0], points[i][1]];
                newPoint[1] += offsetStart + ((width - (width - i)) * (yChange / width));
                newPoints.push(newPoint);
            }
            return newPoints;
        }
        return [];
    };
    Ribbon.prototype.getBlockFontSize = function (topPoints, bottomPoints, padding, maxSize, minSize) {
        if (maxSize === void 0) { maxSize = 40; }
        if (minSize === void 0) { minSize = 10; }
        var startHeight = Math.abs(topPoints[0][1] - bottomPoints[0][1]);
        var endHeight = Math.abs(topPoints[topPoints.length - 1][1] - bottomPoints[bottomPoints.length - 1][1]);
        var space = startHeight < endHeight ? startHeight : endHeight;
        space -= padding * 2;
        if (space < minSize)
            space = minSize;
        if (space > maxSize)
            space = maxSize;
        return space;
    };
    Ribbon.prototype.getWavePathString = function (points) {
        // if(points.length < 2) return '';
        var mapped = _.map(points, function (d) {
            return d.join(',');
        });
        return 'M' + mapped.join(' ');
    };
    Ribbon.prototype.getWavePolygon = function (topPoints, bottomPoints) {
        var allPoints = topPoints.concat(bottomPoints);
        var polyString = '';
        for (var i = 0; i < allPoints.length; i++) {
            polyString += allPoints[i].join(' ') + ' ';
        }
        return polyString;
    };
    Ribbon.prototype.onBlockClick = function (e) {
        var selectedBlock = null;
        for (var i = 0; i < e.path.length; i++) {
            if (e.path[i].nodeName == 'g') {
                selectedBlock = e.path[i].id;
                break;
            }
        }
        if (selectedBlock)
            this.selectBlock(selectedBlock);
    };
    Ribbon.prototype.resizeSVG = function () {
        this.svg.attr({
            width: this.size.svg.width,
            height: this.size.svg.height
        });
    };
    Ribbon.prototype.onResize = function (event) {
        this.size.svg.width = event.target.innerWidth;
        this.size.svg.height = event.target.innerHeight;
        if (this.svg)
            this.resizeSVG();
    };
    Ribbon.prototype.tick = function (c) {
        var _this = this;
        if (c % 2 == 0) {
            // render 30fps
            this.rootPos += this.speed.rest;
            this.updateRibbon();
        }
        requestAnimationFrame(function () {
            _this.tick(c + 1);
        });
    };
    Ribbon.prototype.toogleState = function () {
        this.setState(this.currentState.type == 'home' ? this.states.selected : this.states.home);
    };
    Ribbon.prototype.selectBlock = function (blockId) {
        if (blockId === 'back')
            return this.deselectBlock();
        var selectedBlockPosition = 100;
        for (var i in this.blocks) {
            if (this.blocks[i].id === blockId || this.blocks[i].type === 'back') {
                selectedBlockPosition = this.blocks[i].position.current;
                this.blocks[i].position.target = this.blocks[i].type === 'back' ? 10 : 75;
            }
            else {
                this.blocks[i].position.target = this.blocks[i].position.current < selectedBlockPosition ? this.blocks[i].position.home - 100 : this.blocks[i].position.home + 100;
            }
        }
        this.setState(this.states.selected);
    };
    Ribbon.prototype.deselectBlock = function () {
        for (var i in this.blocks) {
            this.blocks[i].position.target = this.blocks[i].type == 'menu' ? this.blocks[i].position.home : -100;
        }
        this.setState(this.states.home);
    };
    Ribbon.prototype.setState = function (newState) {
        var transitionSpeed = 2;
        var ease = Power2.easeInOut;
        this.currentState.type = newState.type;
        TweenMax.to(this.currentState.start, this.speed.changeState, { top: newState.start.top, left: newState.start.left, thickness: newState.start.thickness, ease: ease });
        TweenMax.to(this.currentState.end, this.speed.changeState, { top: newState.end.top, left: newState.end.left, thickness: newState.end.thickness, ease: ease });
        TweenMax.to(this.currentState.wave, this.speed.changeState, { amplitude: newState.wave.amplitude, frequency: newState.wave.frequency, ease: ease });
        if (this.currentState.wave.transitionSpeed > this.speed.rest) {
            TweenMax.to(this.speed, this.speed.changeState / 2, { rest: newState.wave.transitionSpeed, ease: Power2.easeIn });
            TweenMax.to(this.speed, this.speed.changeState / 2, { rest: this.defaultRestSpeed, delay: this.speed.changeState / 2, ease: Power2.easeOut });
        }
        else {
            TweenMax.to(this.speed, this.speed.changeState, { rest: this.defaultRestSpeed, ease: ease });
        }
        for (var i = 0; i < this.blocks.length; i++) {
            var block = this.blocks[i];
            if (block.position.current !== block.position.target)
                TweenMax.to(block.position, this.speed.changeState, { current: block.position.target, ease: ease });
        }
    };
    return Ribbon;
}());
var ribbon = new Ribbon(Snap('#svg'));
ribbon.init();
@import 'https://fonts.googleapis.com/css?family=Catamaran';

html, body
{
	width: 100%;
	height: 100%;
	margin: 0;
	padding: 0;
	font-family: 'Catamaran', sans-serif;
}

body {
  background: #eee;
  background: linear-gradient(to left, #ddd , #eee);
}

.container
{
	margin: 0;
	padding: 0;
	height: 100%;
	width: 100%;
}

svg
{
	z-index: 10;
}

.block
{
    cursor: pointer;

    text
    {
        fill: white;
    }

    polygon
    {
        fill: white;
        opacity: 0.3;
        transition: opacity 0.3s ease;
    }

    &:hover
    {
        polygon
        {
            opacity: 0.5;
        }
    }
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <meta charset="utf-8"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.4.1/snap.svg-min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.0/TweenMax.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
    <links href="style.css" type="text/css" rel="stylesheet">
  </head>
  <body>
    <div class="container">
      <script src="script.js"></script>
    	<svg id="svg"></svg>
    </div>
  </body>
</html>

由于某些原因,它确实可以在这里工作,但Firefox dev版本告诉我以下TypeError: this.svg is null. script.js:85:9,我似乎无法解决任何问题。对于任何想知道我的朋友想出这个的人,对他而言,它的工作非常好,但他也不知道我能做什么。在回答时请记住,我是新手,所以如果它真的很愚蠢的话,请放轻松。

1 个答案:

答案 0 :(得分:0)

我真的不明白你在这里想做什么但是,Snap方法没有返回任何内容,因为脚本先运行,所以svg标签由于某种原因被删除了。

对HTML进行了轻微修改,它完美无缺。

<html lang="en">
  <head>
    <meta charset="utf-8"/>

    <links href="style.css" type="text/css" rel="stylesheet">
  </head>
  <body>
    <div class="container">     
        <svg id="svg"></svg>
    </div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.4.1/snap.svg-min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.0/TweenMax.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script><script src="script.js"></script>
  </body>
</html>