有时 svg 图表不适合容器,但它在屏幕刷新时有效

Sometimes svg chart doesn't fit in the container but it works when screen refresh

有时 svg 图表看起来比正常图表小。此问题已解决重新加载屏幕。

//Values Graphic
$scope.$watch(vm.dataGraphic.watch, function () {
    var data = vm.dataGraphic.watch ? $scope.$eval(vm.dataGraphic.watch) : vm.dataGraphic;

    setTimeout(sleep,500); //patch to "solve" this issue

    function sleep(){
        vm.dataValues = getDataValues(data);
    }

});
function getDataValues(data) {
    vm.dataGraphic = data || dataGraphicTest;
    if (vm.dataGraphic.values.length == 0) {
        return [];
    } else {
        vm.dataKeyValues = transformForKeyValues(vm.dataGraphic.values, vm.dataGraphic.accumulated);

        vm.barValues = transformBarValues(vm.dataGraphic.values, vm.dataGraphic.limit);
        var lineValues = transformLineValues(vm.barValues, vm.dataGraphic.limit, vm.dataGraphic.accumulated, vm.dataGraphic.startMonthlyLimit);
        vm.maxY = calculateMaxY(vm.barValues, lineValues);

        return [
            {
            "key": vm.dataGraphic.labelX.name,
            "bar": true,
            "color": _graphicsColors.bar,
            "values": vm.barValues
            },
            {
            "key": _graphicsValorPorDefecto,
            "color": _graphicsColors.line,
            "values": lineValues
            }
        ];
    }
}

带有以下 html 标签的 SVG 元素出现了错误的尺寸。

<g class="nvd3 nv-wrap nv-linePlusBar" transform="translate(35,10)">

这个问题不是每次都会发生,但是当它发生时是安排刷新屏幕的。

我认为这个补丁不是个好主意,我想了解发生了什么。

谢谢

我觉得你的问题最终还是出在手表上:

$scope.$watch(vm.dataGraphic.watch, function () {
    var data = vm.dataGraphic.watch ? $scope.$eval(vm.dataGraphic.watch) : vm.dataGraphic;

    setTimeout(sleep,500); //patch to "solve" this issue

    function sleep(){
        vm.dataValues = getDataValues(data);
    }

});

我看到的问题是您正在使用 setTimeout 在手表触发半秒后调用您的睡眠功能。就像现在一样,如果你的 $digest 在 500 毫秒内仍然是 运行 就没问题了。 setTimeout 是一个普通的 JavaScript 函数,因此调用它不会通知 angularjs $digest 结束后有任何更改。 Angular 仅在 'user-initiated' 事件后触发 $digest,例如 ajax、点击、输入数据等(read more here). If the $digest is running, you'll get lucky and angularjs will just happen to see those changes. You'll need to inform angular of your changes using $scope.$apply:

$scope.$watch(vm.dataGraphic.watch, function () {
    var data = vm.dataGraphic.watch ? $scope.$eval(vm.dataGraphic.watch) : vm.dataGraphic;

    setTimeout(sleep,500); //patch to "solve" this issue

    function sleep(){
        vm.dataValues = getDataValues(data);
        $scope.$apply();
    }

});

有很多方法可以使用$scope.$apply,所以一定要查看文档。还可以搜索 'when to use $scope.$apply' 之类的内容,您会发现很多人支持和反对它。它确实会触发另一个 $digest 循环,如果您有很多绑定,或者如果您处于最终摘要循环的末尾并应用导致它重新开始,这可能会很昂贵。

我认为在监视函数中使用 setTimeout 更新模型实际上不是一个好主意。没有它这行不通吗?您可能有一些其他需要以相同方式应用的异步代码。通常,您希望 $scope.$apply 尽可能接近非 angular 异步代码。