问:
Distorting images using FabricJS filters and custom controls, by dragging the corner control points of an image
I am trying to implement distortion in Fabric.js. And it is working preatty good so far. But now I need to make it work when the object has an angle/rotation. And I Cant wrap my head around why it is not working.

I have been following this code. Question

When adding angle to the object the image will move the other corners/controls as well. But when i set the angle to 0 or remove it. It will work. Does any one know how to make it work with the angle/rotation. I want the corners to stay in place.

I tried to add the rotation to the _renderFill function. But did not work.

I also made a new fiddle

```fabric.textureSize = 4096;
// Set default filter backend
fabric.filterBackend = new fabric.WebglFilterBackend();
fabric.isWebglSupported(fabric.textureSize);

fabric.Image.filters.Perspective = class extends fabric.Image.filters.BaseFilter {
    /**
     * Constructor
     * @param {Object} [options] Options object
     */
    constructor(options) {
        super();

        if (options) this.setOptions(options);

        this.applyPixelRatio();
    }

    type = 'Perspective';
    pixelRatio = fabric.devicePixelRatio;
    bounds = {width: 0, height: 0, minX: 0, maxX: 0, minY: 0, maxY: 0};
    hasRelativeCoordinates = true;

    /**
     * Array of attributes to send with buffers. do not modify
     * @private
     *//** @ts-ignore */
    vertexSource = `
        precision mediump float;

        attribute vec2 aPosition;
        attribute vec2 aUvs;

        uniform float uStepW;
        uniform float uStepH;

        varying vec2 vUvs;

        vec2 uResolution;

        void main() {
            vUvs = aUvs;
            uResolution = vec2(uStepW, uStepH);

            gl_Position = vec4(uResolution * aPosition * 2.0 - 1.0, 0.0, 1.0);
        }
    `;

    fragmentSource = `
        precision mediump float;
        varying vec2 vUvs;
        uniform sampler2D uSampler;

        void main() {
            gl_FragColor = texture2D(uSampler, vUvs);
        }
    `;

    /**
     * Return a map of attribute names to WebGLAttributeLocation objects.
     *
     * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.
     * @param {WebGLShaderProgram} program The shader program from which to take attribute locations.
     * @returns {Object} A map of attribute names to attribute locations.
     */
    getAttributeLocations(gl, program) {
        return {
            aPosition: gl.getAttribLocation(program, 'aPosition'),
            aUvs: gl.getAttribLocation(program, 'aUvs'),
        };
    }

    /**
     * Send attribute data from this filter to its shader program on the GPU.
     *
     * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.
     * @param {Object} attributeLocations A map of shader attribute names to their locations.
     */
    sendAttributeData(gl, attributeLocations, data, type = 'aPosition') {
        const attributeLocation = attributeLocations[type];
        if (gl[type + 'vertexBuffer'] == null) {
            gl[type + 'vertexBuffer'] = gl.createBuffer();
        }

        gl.bindBuffer(gl.ARRAY_BUFFER, gl[type+'vertexBuffer']);
        gl.enableVertexAttribArray(attributeLocation);
        gl.vertexAttribPointer(attributeLocation, 2, gl.FLOAT, false, 0, 0);
        gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
    }

    generateSurface() {
        const corners = this.perspectiveCoords;

        const surface = verb.geom.NurbsSurface.byCorners(...corners);
        const tess = surface.tessellate();

        return tess;
    }

    /**
     * Apply the resize filter to the image
     * Determines whether to use WebGL or Canvas2D based on the options.webgl flag.
     *
     * @param {Object} options
     * @param {Number} options.passes The number of filters remaining to be executed
     * @param {Boolean} options.webgl Whether to use webgl to render the filter.
     * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.
     * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.
     * @param {WebGLRenderingContext} options.context The GL context used for rendering.
     * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.
     */
    applyTo(options) {
        if (options.webgl) {
            const { width, height } = this.getPerspectiveBounds();
            options.context.canvas.width = width;
            options.context.canvas.height = height;

            options.destinationWidth = width;
            options.destinationHeight = height;

            this.hasRelativeCoordinates && this.calculateCoordsByCorners();

            this._setupFrameBuffer(options);
            this.applyToWebGL(options);
            this._swapTextures(options);
        }
    }

    applyPixelRatio(coords = this.perspectiveCoords) {
        for(let i = 0; i < coords.length; i++) {
            coords[i][0] *= this.pixelRatio;
            coords[i][1] *= this.pixelRatio;
        }

        return coords;
    }

    getPerspectiveBounds(coords = this.perspectiveCoords) {
        coords = this.perspectiveCoords.slice().map(c => (
            {
                x: c[0],
                y: c[1],
            }
        ));

        this.bounds.minX = fabric.util.array.min(coords, 'x') || 0;
        this.bounds.minY = fabric.util.array.min(coords, 'y') || 0;
        this.bounds.maxX = fabric.util.array.max(coords, 'x') || 0;
        this.bounds.maxY = fabric.util.array.max(coords, 'y') || 0;

        this.bounds.width = Math.abs(this.bounds.maxX - this.bounds.minX);
        this.bounds.height = Math.abs(this.bounds.maxY - this.bounds.minY);

        return {
            width:  this.bounds.width,
            height: this.bounds.height,
            minX:   this.bounds.minX,
            maxX:   this.bounds.maxX,
            minY:   this.bounds.minY,
            maxY:   this.bounds.maxY,
        };
    }

    /**
     * @description coordinates are coming in relative to mockup item sections
     * the following function normalizes the coords based on canvas corners
     *
     * @param {number[]} coords
     */
    calculateCoordsByCorners(coords = this.perspectiveCoords) {
        for(let i = 0; i < coords.length; i++) {
            coords[i][0] -= this.bounds.minX;
            coords[i][1] -= this.bounds.minY;
        }
    }

    /**
     * Apply this filter using webgl.
     *
     * @param {Object} options
     * @param {Number} options.passes The number of filters remaining to be executed
     * @param {Boolean} options.webgl Whether to use webgl to render the filter.
     * @param {WebGLTexture} options.originalTexture The texture of the original input image.
     * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.
     * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.
     * @param {WebGLRenderingContext} options.context The GL context used for rendering.
     * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.
     */
    applyToWebGL(options) {
        const gl = options.context;
        const shader = this.retrieveShader(options);
        const tess = this.generateSurface(options.sourceWidth, options.sourceHeight);
        const indices = new Uint16Array(_.flatten(tess.faces));

        // Clear the canvas first
        this.clear(gl); // !important

        // bind texture buffer
        this.bindTexture(gl, options);

        gl.useProgram(shader.program);

        // create the buffer
        this.indexBuffer(gl, indices);

        this.sendAttributeData(gl, shader.attributeLocations, new Float32Array(_.flatten(tess.points)), 'aPosition');
        this.sendAttributeData(gl, shader.attributeLocations, new Float32Array(_.flatten(tess.uvs)), 'aUvs');

        gl.uniform1f(shader.uniformLocations.uStepW, 1 / gl.canvas.width);
        gl.uniform1f(shader.uniformLocations.uStepH, 1 / gl.canvas.height);

        this.sendUniformData(gl, shader.uniformLocations);
        gl.viewport(0, 0, options.destinationWidth, options.destinationHeight);

        // enable indices up to 4294967296 for webGL 1.0
        gl.getExtension('OES_element_index_uint');
        gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
    }

    clear(gl) {
        gl.clearColor(0, 0, 0, 0);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    }

    bindTexture(gl, options) {
        if (options.pass === 0 && options.originalTexture) {
            gl.bindTexture(gl.TEXTURE_2D, options.originalTexture);
        } else {
            gl.bindTexture(gl.TEXTURE_2D, options.sourceTexture);
        }

        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    }

    indexBuffer(gl, data) {
        const indexBuffer = gl.createBuffer();
        // make this buffer the current 'ELEMENT_ARRAY_BUFFER'
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
        // Fill the current element array buffer with data
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, data, gl.STATIC_DRAW);
    }
};

/**
 * Returns filter instance from an object representation
 * @static
 * @param {Object} object Object to create an instance from
 * @param {function} [callback] to be invoked after filter creation
 * @return {fabric.Image.filters.Perspective} Instance of fabric.Image.filters.Perspective
 */
fabric.Image.filters.Perspective.fromObject = fabric.Image.filters.BaseFilter.fromObject;

/**
 * Photo subclass
 * @class fabric.Photo
 * @extends fabric.Photo
 * @return {fabric.Photo} thisArg
 *
 */
fabric.Photo = class extends fabric.Image {
    type = 'photo';
    repeat = 'no-repeat';
    fill = 'transparent';
    initPerspective = true;

    cacheProperties = fabric.Image.prototype.cacheProperties.concat('perspectiveCoords');

    constructor(src, options) {
        super(options);

        if (options) this.setOptions(options);

        this.on('added', () => {
            const image = new Image();
            image.setAttribute('crossorigin', 'anonymous');
            image.onload = () => {
                this._initElement(image, options);
                this.width = image.width / 2;
                this.height = image.height / 2;
                this.loaded = true;
                this.setCoords();
                this.fire('image:loaded');
            };
            image.src = src;

            this.on('image:loaded', () => {
                !this.perspectiveCoords && this.getInitialPerspective();

                this.togglePerspective();
                this.canvas.requestRenderAll();
            });
        });
    }

    cacheProperties = fabric.Image.prototype.cacheProperties.concat('perspectiveCoords');

    /**
     * @private
     * @param {CanvasRenderingContext2D} ctx Context to render on
     *//** @ts-ignore */
    _render(ctx) {
        fabric.util.setImageSmoothing(ctx, this.imageSmoothing);

        if (this.isMoving !== true && this.resizeFilter && this._needsResize()) {
          this.applyResizeFilters();
        }

        this._stroke(ctx);
        this._renderPaintInOrder(ctx);
    }

    /**
     * @private
     * @param {CanvasRenderingContext2D} ctx Context to render on
     *//** @ts-ignore */
    _renderFill(ctx) {
        var elementToDraw = this._element;
        if (!elementToDraw) return;

        ctx.save();
        const elWidth = elementToDraw.naturalWidth || elementToDraw.width;
        const elHeight = elementToDraw.naturalHeight || elementToDraw.height;
        const width = this.width;
        const height = this.height;

        ctx.translate(-width / 2, -height / 2);

        // get the scale
        const scale = Math.min(width / elWidth, height / elHeight);
        // get the top left position of the image
        const x = (width / 2) - (elWidth / 2) * scale;
        const y = (height / 2) - (elHeight / 2) * scale;

        ctx.drawImage(elementToDraw, x, y, elWidth * scale, elHeight * scale);

        ctx.restore();
    }

    togglePerspective(mode = true) {
        this.set('perspectiveMode', mode);
        // this.set('hasBorders', !mode);

        if (mode === true) {
            this.set('layout', 'fit');

            var lastControl = this.perspectiveCoords.length - 1;

            this.controls = this.perspectiveCoords.reduce((acc, coord, index) => {
                const anchorIndex = index > 0 ? index - 1 : lastControl;
                let name = `prs${index + 1}`;

                acc[name] = new fabric.Control({
                    name,
                    x: -0.5,
                    y: -0.5,
                    actionHandler: this._actionWrapper(anchorIndex, (_, transform, x, y) => {
                        const target = transform.target;
                        const localPoint = target.toLocalPoint(new fabric.Point(x, y), 'left', 'top');

                        coord[0] = localPoint.x / target.scaleX * fabric.devicePixelRatio;
                        coord[1] = localPoint.y / target.scaleY * fabric.devicePixelRatio;

                        target.setCoords();
                        target.applyFilters();

                        return true;
                    }),
                    positionHandler: function (dim, finalMatrix, fabricObject) {
                        const zoom = fabricObject.canvas.getZoom();
                        const scalarX = fabricObject.scaleX * zoom / fabric.devicePixelRatio;
                        const scalarY = fabricObject.scaleY * zoom / fabric.devicePixelRatio;

                        var point = fabric.util.transformPoint({
                                x: this.x * dim.x + this.offsetX + coord[0] * scalarX,
                                y: this.y * dim.y + this.offsetY + coord[1] * scalarY,
                            }, finalMatrix
                        );
                        return point;
                    },
                    cursorStyleHandler: () => 'cell',
                    render: function(ctx, left, top, _, fabricObject) {
                        const zoom = fabricObject.canvas.getZoom();
                        const scalarX = fabricObject.scaleX * zoom / fabric.devicePixelRatio;
                        const scalarY = fabricObject.scaleY * zoom / fabric.devicePixelRatio;

                        ctx.save();
                        ctx.translate(left, top);
                        ctx.rotate(fabric.util.degreesToRadians(fabricObject.angle));
                        ctx.beginPath();

                        ctx.moveTo(0, 0);
                        ctx.strokeStyle = 'green';

                        if (fabricObject.perspectiveCoords[index + 1]) {
                            ctx.strokeStyle = 'green';
                            ctx.lineTo(
                                (fabricObject.perspectiveCoords[index + 1][0] - coord[0]) * scalarX,
                                (fabricObject.perspectiveCoords[index + 1][1] - coord[1]) * scalarY,
                            );
                        } else {
                            ctx.lineTo(
                                (fabricObject.perspectiveCoords[0][0] - coord[0]) * scalarX,
                                (fabricObject.perspectiveCoords[0][1] - coord[1]) * scalarY,
                            );
                        }
                        ctx.stroke();
                        ctx.beginPath();
                        ctx.arc(0, 0, 4, 0, Math.PI * 2);
                        ctx.closePath();
                        ctx.fillStyle = 'green';
                        ctx.fill();
                        ctx.stroke();
                        ctx.restore();
                    },
                    offsetX: 0,
                    offsetY: 0,
                    actionName: 'perspective-coords',
                });

                return acc;
            }, {});
        } else {
            this.controls = fabric.Photo.prototype.controls;
        }

        this.canvas.requestRenderAll();
    }

    _actionWrapper(anchorIndex, fn) {
        return function(eventData, transform, x, y) {
            if (!transform || !eventData) return;

            const { target } = transform;

            target._resetSizeAndPosition(anchorIndex);

            const actionPerformed = fn(eventData, transform, x, y);
            return actionPerformed;
        };
    }

    /**
     * @description manually reset the bounding box after points update
     *
     * @see http://fabricjs.com/custom-controls-polygon
     * @param {number} index
     */
    _resetSizeAndPosition = (index, apply = true) => {
        const absolutePoint = fabric.util.transformPoint({
            x: this.perspectiveCoords[index][0],
            y: this.perspectiveCoords[index][1],
        }, this.calcTransformMatrix());

        let { height, width, left, top } = this._calcDimensions({});

        const widthDiff = (width - this.width) / 2;
        if ((left < 0 && widthDiff > 0) || (left > 0 && widthDiff < 0)) {
            absolutePoint.x -= widthDiff;
        } else {
            absolutePoint.x += widthDiff;
        }

        const heightDiff = (height - this.height) / 2;
        if ((top < 0 && heightDiff > 0) || (top > 0 && heightDiff < 0)) {
            absolutePoint.y -= heightDiff;
        } else {
            absolutePoint.y += heightDiff;
        }
        this._setPositionDimensions({});

        const penBaseSize = this._getNonTransformedDimensions();
        const newX = (this.perspectiveCoords[index][0]) / penBaseSize.x;
        const newY = (this.perspectiveCoords[index][1]) / penBaseSize.y;

        this.setPositionByOrigin(absolutePoint, newX + 0.5, newY + 0.5);

        apply && this._applyPointsOffset();
    }

    /**
     * This is modified version of the internal fabric function
     * this helps determine the size and the location of the path
     *
     * @param {object} options
     */
    _setPositionDimensions(options) {
        const { left, top, width, height } = this._calcDimensions(options);

        this.width = width;
        this.height = height;

        var correctLeftTop = this.translateToGivenOrigin(
            {
                x: left,
                y: top,
            },
            'left',
            'top',
            this.originX,
            this.originY
        );

        if (typeof options.left === 'undefined') {
            this.left = correctLeftTop.x;
        }
        if (typeof options.top === 'undefined') {
            this.top = correctLeftTop.y;
        }

        this.pathOffset = {
            x: left,
            y: top,
        };

        return { left, top, width, height };
    }

    /**
     * @description this is based on fabric.Path._calcDimensions
     *
     * @private
     */
    _calcDimensions() {
        const coords = this.perspectiveCoords.slice().map(c => (
            {
                x: c[0] / fabric.devicePixelRatio,
                y: c[1] / fabric.devicePixelRatio,
            }
        ));

        const minX = fabric.util.array.min(coords, 'x') || 0;
        const minY = fabric.util.array.min(coords, 'y') || 0;
        const maxX = fabric.util.array.max(coords, 'x') || 0;
        const maxY = fabric.util.array.max(coords, 'y') || 0;

        const width = Math.abs(maxX - minX);
        const height = Math.abs(maxY - minY);

        return {
            left: minX,
            top: minY,
            width: width,
            height: height,
        };
    }

    /**
     * @description This is modified version of the internal fabric function
     * this subtracts the path offset from each path points
     */
    _applyPointsOffset() {
        for (let i = 0; i < this.perspectiveCoords.length; i++) {
            const coord = this.perspectiveCoords[i];

            coord[0] -= this.pathOffset.x;
            coord[1] -= this.pathOffset.y;
        }
    }

    /**
     * @description generate the initial coordinates for warping, based on image dimensions
     *
     */
    getInitialPerspective() {
        let w = this.getScaledWidth();
        let h = this.getScaledHeight();

        const perspectiveCoords = [
            [0, 0], // top left
            [w, 0], // top right
            [w, h], // bottom right
            [0, h], // bottom left
        ];

        this.perspectiveCoords = perspectiveCoords;

        const perspectiveFilter = new fabric.Image.filters.Perspective({
            hasRelativeCoordinates: false,
            pixelRatio: fabric.devicePixelRatio, // the Photo is already retina ready
            perspectiveCoords
        });

        this.filters.push(perspectiveFilter);
        this.applyFilters();

        return perspectiveCoords;
    }
};

/**
 * Creates an instance of fabric.Photo from its object representation
 * @static
 * @param {Object} object Object to create an instance from
 * @param {Function} callback Callback to invoke when an image instance is created
 */
fabric.Photo.fromObject = function(_object, callback) {
    const object = fabric.util.object.clone(_object);
    object.layout = _object.layout;

    fabric.util.loadImage(object.src, function(img, isError) {
        if (isError) {
            callback && callback(null, true);

            return;
        }
        fabric.Photo.prototype._initFilters.call(object, object.filters, function(filters) {
            object.filters = filters || [];
            fabric.Photo.prototype._initFilters.call(object, [object.resizeFilter], function(resizeFilters) {
                object.resizeFilter = resizeFilters[0];

                fabric.util.enlivenObjects([object.clipPath], function(enlivedProps) {
                    object.clipPath = enlivedProps[0];
                    var image = new fabric.Photo(img, object);

                    callback(image, false);
                });
            });
        });
    }, null, object.crossOrigin || 'anonymous');
};

const canvas = new fabric.Canvas(document.getElementById('canvas'), {
  backgroundColor: 'white',
  enableRetinaScaling: true,
});

function resizeCanvas() {
  canvas.setWidth(window.innerWidth);
  canvas.setHeight(window.innerHeight);
}

resizeCanvas();
window.addEventListener('resize', () => resizeCanvas(), false);

const photo = new fabric.Photo('data:image/jpeg;base64,[encoded data, 6196 characters]', {
  left: canvas.getWidth() / 2,
  top: canvas.getHeight() / 2,
  originX: 'center',
  originY: 'center',
  // this make it not work
  angle:90
});

canvas.add(photo);
canvas.setActiveObject(photo);
```

Body:
I am trying to implement distortion in Fabric.js. And it is working preatty good so far. But now I need to make it work when the object has an angle/rotation. And I Cant wrap my head around why it is not working.

I have been following this code. Question

When adding angle to the object the image will move the other corners/controls as well. But when i set the angle to 0 or remove it. It will work. Does any one know how to make it work with the angle/rotation. I want the corners to stay in place.

I tried to add the rotation to the _renderFill function. But did not work.

I also made a new fiddle

fabric.textureSize = 4096;
// Set default filter backend
fabric.filterBackend = new fabric.WebglFilterBackend();
fabric.isWebglSupported(fabric.textureSize);

fabric.Image.filters.Perspective = class extends fabric.Image.filters.BaseFilter {
    /**
     * Constructor
     * @param {Object} [options] Options object
     */
    constructor(options) {
        super();

        if (options) this.setOptions(options);

        this.applyPixelRatio();
    }

    type = 'Perspective';
    pixelRatio = fabric.devicePixelRatio;
    bounds = {width: 0, height: 0, minX: 0, maxX: 0, minY: 0, maxY: 0};
    hasRelativeCoordinates = true;

    /**
     * Array of attributes to send with buffers. do not modify
     * @private
     *//** @ts-ignore */
    vertexSource = `
        precision mediump float;

        attribute vec2 aPosition;
        attribute vec2 aUvs;

        uniform float uStepW;
        uniform float uStepH;

        varying vec2 vUvs;

        vec2 uResolution;

        void main() {
            vUvs = aUvs;
            uResolution = vec2(uStepW, uStepH);

            gl_Position = vec4(uResolution * aPosition * 2.0 - 1.0, 0.0, 1.0);
        }
    `;

    fragmentSource = `
        precision mediump float;
        varying vec2 vUvs;
        uniform sampler2D uSampler;

        void main() {
            gl_FragColor = texture2D(uSampler, vUvs);
        }
    `;

    /**
     * Return a map of attribute names to WebGLAttributeLocation objects.
     *
     * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.
     * @param {WebGLShaderProgram} program The shader program from which to take attribute locations.
     * @returns {Object} A map of attribute names to attribute locations.
     */
    getAttributeLocations(gl, program) {
        return {
            aPosition: gl.getAttribLocation(program, 'aPosition'),
            aUvs: gl.getAttribLocation(program, 'aUvs'),
        };
    }

    /**
     * Send attribute data from this filter to its shader program on the GPU.
     *
     * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.
     * @param {Object} attributeLocations A map of shader attribute names to their locations.
     */
    sendAttributeData(gl, attributeLocations, data, type = 'aPosition') {
        const attributeLocation = attributeLocations[type];
        if (gl[type + 'vertexBuffer'] == null) {
            gl[type + 'vertexBuffer'] = gl.createBuffer();
        }

        gl.bindBuffer(gl.ARRAY_BUFFER, gl[type+'vertexBuffer']);
        gl.enableVertexAttribArray(attributeLocation);
        gl.vertexAttribPointer(attributeLocation, 2, gl.FLOAT, false, 0, 0);
        gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
    }

    generateSurface() {
        const corners = this.perspectiveCoords;

        const surface = verb.geom.NurbsSurface.byCorners(...corners);
        const tess = surface.tessellate();

        return tess;
    }

    /**
     * Apply the resize filter to the image
     * Determines whether to use WebGL or Canvas2D based on the options.webgl flag.
     *
     * @param {Object} options
     * @param {Number} options.passes The number of filters remaining to be executed
     * @param {Boolean} options.webgl Whether to use webgl to render the filter.
     * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.
     * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.
     * @param {WebGLRenderingContext} options.context The GL context used for rendering.
     * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.
     */
    applyTo(options) {
        if (options.webgl) {
            const { width, height } = this.getPerspectiveBounds();
            options.context.canvas.width = width;
            options.context.canvas.height = height;

            options.destinationWidth = width;
            options.destinationHeight = height;

            this.hasRelativeCoordinates && this.calculateCoordsByCorners();

            this._setupFrameBuffer(options);
            this.applyToWebGL(options);
            this._swapTextures(options);
        }
    }

    applyPixelRatio(coords = this.perspectiveCoords) {
        for(let i = 0; i < coords.length; i++) {
            coords[i][0] *= this.pixelRatio;
            coords[i][1] *= this.pixelRatio;
        }

        return coords;
    }

    getPerspectiveBounds(coords = this.perspectiveCoords) {
        coords = this.perspectiveCoords.slice().map(c => (
            {
                x: c[0],
                y: c[1],
            }
        ));

        this.bounds.minX = fabric.util.array.min(coords, 'x') || 0;
        this.bounds.minY = fabric.util.array.min(coords, 'y') || 0;
        this.bounds.maxX = fabric.util.array.max(coords, 'x') || 0;
        this.bounds.maxY = fabric.util.array.max(coords, 'y') || 0;

        this.bounds.width = Math.abs(this.bounds.maxX - this.bounds.minX);
        this.bounds.height = Math.abs(this.bounds.maxY - this.bounds.minY);

        return {
            width:  this.bounds.width,
            height: this.bounds.height,
            minX:   this.bounds.minX,
            maxX:   this.bounds.maxX,
            minY:   this.bounds.minY,
            maxY:   this.bounds.maxY,
        };
    }

    /**
     * @description coordinates are coming in relative to mockup item sections
     * the following function normalizes the coords based on canvas corners
     *
     * @param {number[]} coords
     */
    calculateCoordsByCorners(coords = this.perspectiveCoords) {
        for(let i = 0; i < coords.length; i++) {
            coords[i][0] -= this.bounds.minX;
            coords[i][1] -= this.bounds.minY;
        }
    }

    /**
     * Apply this filter using webgl.
     *
     * @param {Object} options
     * @param {Number} options.passes The number of filters remaining to be executed
     * @param {Boolean} options.webgl Whether to use webgl to render the filter.
     * @param {WebGLTexture} options.originalTexture The texture of the original input image.
     * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.
     * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.
     * @param {WebGLRenderingContext} options.context The GL context used for rendering.
     * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.
     */
    applyToWebGL(options) {
        const gl = options.context;
        const shader = this.retrieveShader(options);
        const tess = this.generateSurface(options.sourceWidth, options.sourceHeight);
        const indices = new Uint16Array(_.flatten(tess.faces));

        // Clear the canvas first
        this.clear(gl); // !important

        // bind texture buffer
        this.bindTexture(gl, options);

        gl.useProgram(shader.program);

        // create the buffer
        this.indexBuffer(gl, indices);

        this.sendAttributeData(gl, shader.attributeLocations, new Float32Array(_.flatten(tess.points)), 'aPosition');
        this.sendAttributeData(gl, shader.attributeLocations, new Float32Array(_.flatten(tess.uvs)), 'aUvs');

        gl.uniform1f(shader.uniformLocations.uStepW, 1 / gl.canvas.width);
        gl.uniform1f(shader.uniformLocations.uStepH, 1 / gl.canvas.height);

        this.sendUniformData(gl, shader.uniformLocations);
        gl.viewport(0, 0, options.destinationWidth, options.destinationHeight);

        // enable indices up to 4294967296 for webGL 1.0
        gl.getExtension('OES_element_index_uint');
        gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
    }

    clear(gl) {
        gl.clearColor(0, 0, 0, 0);
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    }

    bindTexture(gl, options) {
        if (options.pass === 0 && options.originalTexture) {
            gl.bindTexture(gl.TEXTURE_2D, options.originalTexture);
        } else {
            gl.bindTexture(gl.TEXTURE_2D, options.sourceTexture);
        }

        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    }

    indexBuffer(gl, data) {
        const indexBuffer = gl.createBuffer();
        // make this buffer the current 'ELEMENT_ARRAY_BUFFER'
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
        // Fill the current element array buffer with data
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, data, gl.STATIC_DRAW);
    }
};

/**
 * Returns filter instance from an object representation
 * @static
 * @param {Object} object Object to create an instance from
 * @param {function} [callback] to be invoked after filter creation
 * @return {fabric.Image.filters.Perspective} Instance of fabric.Image.filters.Perspective
 */
fabric.Image.filters.Perspective.fromObject = fabric.Image.filters.BaseFilter.fromObject;

/**
 * Photo subclass
 * @class fabric.Photo
 * @extends fabric.Photo
 * @return {fabric.Photo} thisArg
 *
 */
fabric.Photo = class extends fabric.Image {
    type = 'photo';
    repeat = 'no-repeat';
    fill = 'transparent';
    initPerspective = true;

    cacheProperties = fabric.Image.prototype.cacheProperties.concat('perspectiveCoords');

    constructor(src, options) {
        super(options);

        if (options) this.setOptions(options);

        this.on('added', () => {
            const image = new Image();
            image.setAttribute('crossorigin', 'anonymous');
            image.onload = () => {
                this._initElement(image, options);
                this.width = image.width / 2;
                this.height = image.height / 2;
                this.loaded = true;
                this.setCoords();
                this.fire('image:loaded');
            };
            image.src = src;

            this.on('image:loaded', () => {
                !this.perspectiveCoords && this.getInitialPerspective();

                this.togglePerspective();
                this.canvas.requestRenderAll();
            });
        });
    }

    cacheProperties = fabric.Image.prototype.cacheProperties.concat('perspectiveCoords');

    /**
     * @private
     * @param {CanvasRenderingContext2D} ctx Context to render on
     *//** @ts-ignore */
    _render(ctx) {
        fabric.util.setImageSmoothing(ctx, this.imageSmoothing);

        if (this.isMoving !== true && this.resizeFilter && this._needsResize()) {
          this.applyResizeFilters();
        }

        this._stroke(ctx);
        this._renderPaintInOrder(ctx);
    }

    /**
     * @private
     * @param {CanvasRenderingContext2D} ctx Context to render on
     *//** @ts-ignore */
    _renderFill(ctx) {
        var elementToDraw = this._element;
        if (!elementToDraw) return;

        ctx.save();
        const elWidth = elementToDraw.naturalWidth || elementToDraw.width;
        const elHeight = elementToDraw.naturalHeight || elementToDraw.height;
        const width = this.width;
        const height = this.height;

        ctx.translate(-width / 2, -height / 2);

        // get the scale
        const scale = Math.min(width / elWidth, height / elHeight);
        // get the top left position of the image
        const x = (width / 2) - (elWidth / 2) * scale;
        const y = (height / 2) - (elHeight / 2) * scale;

        ctx.drawImage(elementToDraw, x, y, elWidth * scale, elHeight * scale);

        ctx.restore();
    }

    togglePerspective(mode = true) {
        this.set('perspectiveMode', mode);
        // this.set('hasBorders', !mode);

        if (mode === true) {
            this.set('layout', 'fit');

            var lastControl = this.perspectiveCoords.length - 1;

            this.controls = this.perspectiveCoords.reduce((acc, coord, index) => {
                const anchorIndex = index > 0 ? index - 1 : lastControl;
                let name = `prs${index + 1}`;

                acc[name] = new fabric.Control({
                    name,
                    x: -0.5,
                    y: -0.5,
                    actionHandler: this._actionWrapper(anchorIndex, (_, transform, x, y) => {
                        const target = transform.target;
                        const localPoint = target.toLocalPoint(new fabric.Point(x, y), 'left', 'top');

                        coord[0] = localPoint.x / target.scaleX * fabric.devicePixelRatio;
                        coord[1] = localPoint.y / target.scaleY * fabric.devicePixelRatio;

                        target.setCoords();
                        target.applyFilters();

                        return true;
                    }),
                    positionHandler: function (dim, finalMatrix, fabricObject) {
                        const zoom = fabricObject.canvas.getZoom();
                        const scalarX = fabricObject.scaleX * zoom / fabric.devicePixelRatio;
                        const scalarY = fabricObject.scaleY * zoom / fabric.devicePixelRatio;

                        var point = fabric.util.transformPoint({
                                x: this.x * dim.x + this.offsetX + coord[0] * scalarX,
                                y: this.y * dim.y + this.offsetY + coord[1] * scalarY,
                            }, finalMatrix
                        );
                        return point;
                    },
                    cursorStyleHandler: () => 'cell',
                    render: function(ctx, left, top, _, fabricObject) {
                        const zoom = fabricObject.canvas.getZoom();
                        const scalarX = fabricObject.scaleX * zoom / fabric.devicePixelRatio;
                        const scalarY = fabricObject.scaleY * zoom / fabric.devicePixelRatio;

                        ctx.save();
                        ctx.translate(left, top);
                        ctx.rotate(fabric.util.degreesToRadians(fabricObject.angle));
                        ctx.beginPath();

                        ctx.moveTo(0, 0);
                        ctx.strokeStyle = 'green';

                        if (fabricObject.perspectiveCoords[index + 1]) {
                            ctx.strokeStyle = 'green';
                            ctx.lineTo(
                                (fabricObject.perspectiveCoords[index + 1][0] - coord[0]) * scalarX,
                                (fabricObject.perspectiveCoords[index + 1][1] - coord[1]) * scalarY,
                            );
                        } else {
                            ctx.lineTo(
                                (fabricObject.perspectiveCoords[0][0] - coord[0]) * scalarX,
                                (fabricObject.perspectiveCoords[0][1] - coord[1]) * scalarY,
                            );
                        }
                        ctx.stroke();
                        ctx.beginPath();
                        ctx.arc(0, 0, 4, 0, Math.PI * 2);
                        ctx.closePath();
                        ctx.fillStyle = 'green';
                        ctx.fill();
                        ctx.stroke();
                        ctx.restore();
                    },
                    offsetX: 0,
                    offsetY: 0,
                    actionName: 'perspective-coords',
                });

                return acc;
            }, {});
        } else {
            this.controls = fabric.Photo.prototype.controls;
        }

        this.canvas.requestRenderAll();
    }

    _actionWrapper(anchorIndex, fn) {
        return function(eventData, transform, x, y) {
            if (!transform || !eventData) return;

            const { target } = transform;

            target._resetSizeAndPosition(anchorIndex);

            const actionPerformed = fn(eventData, transform, x, y);
            return actionPerformed;
        };
    }

    /**
     * @description manually reset the bounding box after points update
     *
     * @see http://fabricjs.com/custom-controls-polygon
     * @param {number} index
     */
    _resetSizeAndPosition = (index, apply = true) => {
        const absolutePoint = fabric.util.transformPoint({
            x: this.perspectiveCoords[index][0],
            y: this.perspectiveCoords[index][1],
        }, this.calcTransformMatrix());

        let { height, width, left, top } = this._calcDimensions({});

        const widthDiff = (width - this.width) / 2;
        if ((left < 0 && widthDiff > 0) || (left > 0 && widthDiff < 0)) {
            absolutePoint.x -= widthDiff;
        } else {
            absolutePoint.x += widthDiff;
        }

        const heightDiff = (height - this.height) / 2;
        if ((top < 0 && heightDiff > 0) || (top > 0 && heightDiff < 0)) {
            absolutePoint.y -= heightDiff;
        } else {
            absolutePoint.y += heightDiff;
        }
        this._setPositionDimensions({});

        const penBaseSize = this._getNonTransformedDimensions();
        const newX = (this.perspectiveCoords[index][0]) / penBaseSize.x;
        const newY = (this.perspectiveCoords[index][1]) / penBaseSize.y;

        this.setPositionByOrigin(absolutePoint, newX + 0.5, newY + 0.5);

        apply && this._applyPointsOffset();
    }

    /**
     * This is modified version of the internal fabric function
     * this helps determine the size and the location of the path
     *
     * @param {object} options
     */
    _setPositionDimensions(options) {
        const { left, top, width, height } = this._calcDimensions(options);

        this.width = width;
        this.height = height;

        var correctLeftTop = this.translateToGivenOrigin(
            {
                x: left,
                y: top,
            },
            'left',
            'top',
            this.originX,
            this.originY
        );

        if (typeof options.left === 'undefined') {
            this.left = correctLeftTop.x;
        }
        if (typeof options.top === 'undefined') {
            this.top = correctLeftTop.y;
        }

        this.pathOffset = {
            x: left,
            y: top,
        };

        return { left, top, width, height };
    }

    /**
     * @description this is based on fabric.Path._calcDimensions
     *
     * @private
     */
    _calcDimensions() {
        const coords = this.perspectiveCoords.slice().map(c => (
            {
                x: c[0] / fabric.devicePixelRatio,
                y: c[1] / fabric.devicePixelRatio,
            }
        ));

        const minX = fabric.util.array.min(coords, 'x') || 0;
        const minY = fabric.util.array.min(coords, 'y') || 0;
        const maxX = fabric.util.array.max(coords, 'x') || 0;
        const maxY = fabric.util.array.max(coords, 'y') || 0;

        const width = Math.abs(maxX - minX);
        const height = Math.abs(maxY - minY);

        return {
            left: minX,
            top: minY,
            width: width,
            height: height,
        };
    }

    /**
     * @description This is modified version of the internal fabric function
     * this subtracts the path offset from each path points
     */
    _applyPointsOffset() {
        for (let i = 0; i < this.perspectiveCoords.length; i++) {
            const coord = this.perspectiveCoords[i];

            coord[0] -= this.pathOffset.x;
            coord[1] -= this.pathOffset.y;
        }
    }

    /**
     * @description generate the initial coordinates for warping, based on image dimensions
     *
     */
    getInitialPerspective() {
        let w = this.getScaledWidth();
        let h = this.getScaledHeight();

        const perspectiveCoords = [
            [0, 0], // top left
            [w, 0], // top right
            [w, h], // bottom right
            [0, h], // bottom left
        ];

        this.perspectiveCoords = perspectiveCoords;

        const perspectiveFilter = new fabric.Image.filters.Perspective({
            hasRelativeCoordinates: false,
            pixelRatio: fabric.devicePixelRatio, // the Photo is already retina ready
            perspectiveCoords
        });

        this.filters.push(perspectiveFilter);
        this.applyFilters();

        return perspectiveCoords;
    }
};

/**
 * Creates an instance of fabric.Photo from its object representation
 * @static
 * @param {Object} object Object to create an instance from
 * @param {Function} callback Callback to invoke when an image instance is created
 */
fabric.Photo.fromObject = function(_object, callback) {
    const object = fabric.util.object.clone(_object);
    object.layout = _object.layout;

    fabric.util.loadImage(object.src, function(img, isError) {
        if (isError) {
            callback && callback(null, true);

            return;
        }
        fabric.Photo.prototype._initFilters.call(object, object.filters, function(filters) {
            object.filters = filters || [];
            fabric.Photo.prototype._initFilters.call(object, [object.resizeFilter], function(resizeFilters) {
                object.resizeFilter = resizeFilters[0];

                fabric.util.enlivenObjects([object.clipPath], function(enlivedProps) {
                    object.clipPath = enlivedProps[0];
                    var image = new fabric.Photo(img, object);

                    callback(image, false);
                });
            });
        });
    }, null, object.crossOrigin || 'anonymous');
};

const canvas = new fabric.Canvas(document.getElementById('canvas'), {
  backgroundColor: 'white',
  enableRetinaScaling: true,
});

function resizeCanvas() {
  canvas.setWidth(window.innerWidth);
  canvas.setHeight(window.innerHeight);
}

resizeCanvas();
window.addEventListener('resize', () => resizeCanvas(), false);

const photo = new fabric.Photo('data:image/jpeg;base64,[encoded data, 6196 characters]', {
  left: canvas.getWidth() / 2,
  top: canvas.getHeight() / 2,
  originX: 'center',
  originY: 'center',
  // this make it not work
  angle:90
});

canvas.add(photo);
canvas.setActiveObject(photo);


来源: stackexchange

问:
Vue3- Vuetify - Infinite scroll like instagram/facebook
I'm developing a website that I want to add a infinite scroll feature.

This site is currently using vue3 and vuetify next.

The following code is a component with a default slot.(It's working, but not as I wanted)

Component

<template>

    <slot />
    <VRow v-if="data?.loadMoreSection?.showLoadMoreSection" class="mt-10" no-gutters>
      <VContainer fluid>
        <VRow
          v-if="data?.loadMoreSection?.showScrollDownOrLoadMoreText && !data.delayScroll"
        >
          <VSpacer />
          <VCol cols="auto">

              {{
                getText({
                  ...(data?.loadMoreSection?.scrollDownOrLoadMoreText ?? {}),
                  params: { type: getText(data?.loadMoreSection?.loadMoreType) },
                })
              }}

              {{ getText(data?.loadMoreSection?.scrollDownOrLoadMoreText) }}

          </VCol>
          <VSpacer />
        </VRow>
        <VRow v-if="data?.loadMoreSection?.showLoadMoreButton">
          <VSpacer />
          <VCol cols="auto">
            <VBtn @click.stop="onLoadMore">

                {{
                  getText({
                    ...(data?.loadMoreSection?.loadMoreButtonText ?? {}),
                    params: { type: getText(data?.loadMoreSection?.loadMoreType) },
                  })
                }}

                {{ getText(data?.loadMoreSection?.loadMoreButtonText) }}

            </VBtn>
          </VCol>
          <VSpacer />
        </VRow>
      </VContainer>
    </VRow>

</template>

```
<p><strong>Usage Example</strong></p>
<pre class="lang-html prettyprint-override"><code><template>
  <InfiniteScrollLoader
    @on-scroll="fetchData"
    @on-load-more="fetchData"
    :scroll-timeout-ms="5000"
    :disable-scroll="data.loading"
    :loadMoreSection="props.loadMoreSection"
  >
     <div>content</div>
  </InfiniteScrollLoader>
</template>
<script setup lang="ts">
async function fetchData(){
  await setTimeout(()=>console.log('fetched'),5000)
}
</script>
</code>```

I just want to make this component more smooth. But I'm terrible working with css/animations and etc, I don't have any idea how to implement it.

ContentLicense: CC BY-SA 4.0

Body:
I'm developing a website that I want to add a infinite scroll feature.

This site is currently using vue3 and vuetify next.

The following code is a component with a default slot.(It's working, but not as I wanted)

Component

<template>

    <slot />
    <VRow v-if="data?.loadMoreSection?.showLoadMoreSection" class="mt-10" no-gutters>
      <VContainer fluid>
        <VRow
          v-if="data?.loadMoreSection?.showScrollDownOrLoadMoreText && !data.delayScroll"
        >
          <VSpacer />
          <VCol cols="auto">

              {{
                getText({
                  ...(data?.loadMoreSection?.scrollDownOrLoadMoreText ?? {}),
                  params: { type: getText(data?.loadMoreSection?.loadMoreType) },
                })
              }}

              {{ getText(data?.loadMoreSection?.scrollDownOrLoadMoreText) }}

          </VCol>
          <VSpacer />
        </VRow>
        <VRow v-if="data?.loadMoreSection?.showLoadMoreButton">
          <VSpacer />
          <VCol cols="auto">
            <VBtn @click.stop="onLoadMore">

                {{
                  getText({
                    ...(data?.loadMoreSection?.loadMoreButtonText ?? {}),
                    params: { type: getText(data?.loadMoreSection?.loadMoreType) },
                  })
                }}

                {{ getText(data?.loadMoreSection?.loadMoreButtonText) }}

            </VBtn>
          </VCol>
          <VSpacer />
        </VRow>
      </VContainer>
    </VRow>

</template>

Usage Example

<template>
  <InfiniteScrollLoader
    @on-scroll="fetchData"
    @on-load-more="fetchData"
    :scroll-timeout-ms="5000"
    :disable-scroll="data.loading"
    :loadMoreSection="props.loadMoreSection"
  >

content

  </InfiniteScrollLoader>
</template>

I just want to make this component more smooth. But I'm terrible working with css/animations and etc, I don't have any idea how to implement it.


问:
All the Document update in collection mongodb and php
I want to update all the documents in that collection.  I user mongo db4.2</p>
```<code>$test='abc';
$SaveAs="abc";
    $update = array('SaveAs' => $SaveAs);
                $updateResult = $testCollection->update
                    (
                        array('test' => $test),
                        array('$set' => $update)
                    );
This is not working for me.
</code>```

Body:
I want to update all the documents in that collection.  I user mongo db4.2

$test='abc';
$SaveAs="abc";
    $update = array('SaveAs' => $SaveAs);
                $updateResult = $testCollection->update
                    (
                        array('test' => $test),
                        array('$set' => $update)
                    );
This is not working for me.


问:
ContentScale not working properly in Jetpack Compose
I have a simple compose UI using Image composable. Whenever I set the little image to my composable size, the image does not crop properly and some paddings showed. My drawable size is 125x125 and my composable size is 350dp. Here is my code example:

```<code>Image(
        painter = painterResource(id = R.drawable.sample_image_2),
        contentDescription = "Player Main Image",
        modifier = Modifier
            .size(350.dp)
            .border(BorderStroke(1.dp, Color.Green))
            .clip(RoundedCornerShape(10))
            .align(CenterHorizontally)
            .padding(0.dp)
            .clickable { },
        contentScale = ContentScale.Crop,
    )
</code>```

Body:
I have a simple compose UI using Image composable. Whenever I set the little image to my composable size, the image does not crop properly and some paddings showed. My drawable size is 125x125 and my composable size is 350dp. Here is my code example:

Image(
        painter = painterResource(id = R.drawable.sample_image_2),
        contentDescription = "Player Main Image",
        modifier = Modifier
            .size(350.dp)
            .border(BorderStroke(1.dp, Color.Green))
            .clip(RoundedCornerShape(10))
            .align(CenterHorizontally)
            .padding(0.dp)
            .clickable { },
        contentScale = ContentScale.Crop,
    )


问:
All combinations from 1 to n of length k in Google Sheets
In Google Sheets, how can I generate a list of the combinations of a given length of numbers between 1 and n?

For example all combinations of length 2 from 1 to 4 would be:

1,2

1,3

1,4

2,3

2,4

3,4


问:
Tracking motion of pixels on screen and sound alarm if there is a change
I have a question. I want to track a certain area of a screen for changes in pixels. Like when I enter a zoom conference I get in waiting area. And if there is a change (person started conference or let me in) I want computer to sound alarm.

I am quit noob in this theme so I would be greatefull if you could help me.


问:
React not render HTML when data change
I am working on a project that uses NextJs and ReactJs. I have a pagination where numbers are returned according to a range and displayed in front. but it is not working properly.

This is my code:

```<code>const {
onPageChange,
totalCount,
siblingCount = 1,
currentPage,
pageSize,
nextDisabled,
  } = props;
    const paginationRange = usePagination({
    currentPage,
    totalCount,
    siblingCount,
    pageSize,
  });
if (currentPage === 0 || paginationRange.length < 2) {
   return null;
}
const onNext = () => {
 if (!nextDisabled) {
   onPageChange(currentPage + 1);
 }
};

const onPrevious = () => {
  if (currentPage!==1) {
     setNumber(currentPage - 1);
     onPageChange(currentPage - 1);
 }
};

{paginationRange.map((pageNumber) => {

          if (pageNumber === DOTS) {
            return (
              <span
                key={"page" + pageNumber}
                className="relative mx-[1px] inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300"
              >
                ...
              </span>
            );
          }

          return (
            <li
              key={"pageNUm" + pageNumber}

              onClick={() => onPageChange(pageNumber)}
              className={`relative items-center hidden mx-[1px] cursor-pointer px-4 py-2 text-sm font-medium   border border-gray-300  focus:z-20 md:inline-flex
              ${currentPage===pageNumber?'bg-blue-500 text-white':'bg-white text-gray-500 hover:bg-gray-50'}`}
            >
              {pageNumber}
            </li>
          );
        })}
</code>```

You can see more details in these picture

In this picture as you see that dots before number 2 is still exist although there is not on new data in above picture.

Title: React not render HTML when data change

Body:
I am working on a project that uses NextJs and ReactJs. I have a pagination where numbers are returned according to a range and displayed in front. but it is not working properly.

This is my code:

const {
onPageChange,
totalCount,
siblingCount = 1,
currentPage,
pageSize,
nextDisabled,
  } = props;
    const paginationRange = usePagination({
    currentPage,
    totalCount,
    siblingCount,
    pageSize,
  });
if (currentPage === 0 || paginationRange.length < 2) {
   return null;
}
const onNext = () => {
 if (!nextDisabled) {
   onPageChange(currentPage + 1);
 }
};

const onPrevious = () => {
  if (currentPage!==1) {
     setNumber(currentPage - 1);
     onPageChange(currentPage - 1);
 }
};

{paginationRange.map((pageNumber) => {

          if (pageNumber === DOTS) {
            return (

                ...

            );
          }

          return (

 onPageChange(pageNumber)}
              className={`relative items-center hidden mx-[1px] cursor-pointer px-4 py-2 text-sm font-medium   border border-gray-300  focus:z-20 md:inline-flex
              ${currentPage===pageNumber?'bg-blue-500 text-white':'bg-white text-gray-500 hover:bg-gray-50'}`}
            >
              {pageNumber}

          );
        })}

You can see more details in these picture

In this picture as you see that dots before number 2 is still exist although there is not on new data in above picture.


问:
Duplicate Data Stored in django via celery task
I think celery task is calling twice
Here is my code

```<code>@task(run_every=crontab(minute="*/1"), queue="accountability")
def analyse():
    with transaction.atomic():
         analyzed_record, _ = Model.objects.get_or_create(
                    invoice_tag=invoice_tags,
                    product_name="demo"
                )
                analyzed_record.current = 0
                analyzed_record.prev = 1
                analyzed_record.invoiced = 2
                analyzed_record.save()
</code>```

I am using this celery args
celery worker --beat --app=demo --concurrency=10 --loglevel=INFO -Q calculate_cost,accountability,scriptQ,ScriptQ,defaultQ

I am expecting that if i am using get_or_create then object data must be unique

Body:
I think celery task is calling twice
Here is my code

@task(run_every=crontab(minute="*/1"), queue="accountability")
def analyse():
    with transaction.atomic():
         analyzed_record, _ = Model.objects.get_or_create(
                    invoice_tag=invoice_tags,
                    product_name="demo"
                )
                analyzed_record.current = 0
                analyzed_record.prev = 1
                analyzed_record.invoiced = 2
                analyzed_record.save()

I am using this celery args
celery worker --beat --app=demo --concurrency=10 --loglevel=INFO -Q calculate_cost,accountability,scriptQ,ScriptQ,defaultQ

I am expecting that if i am using get_or_create then object data must be unique


问:
Issue in thread pool using Spring boot
we are having issues when accessing to application , the application is completely down, We are using SPring boot and has below Jars in lib folder. We are getting connection issues to pool and application is not accessible.

In tomcat tool box xml file we have

```<code><poolAttribute>
                                    <Name>factory</Name>
                                     <Value>org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory</Value>
                                  </poolAttribute>
</code>```

Title: Issue in thread pool using Spring boot

Body:
we are having issues when accessing to application , the application is completely down, We are using SPring boot and has below Jars in lib folder. We are getting connection issues to pool and application is not accessible.

In tomcat tool box xml file we have

<poolAttribute>
                                    <Name>factory</Name>
                                     <Value>org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory</Value>
                                  </poolAttribute>


问:
Mockito for mocking TCP Calls
How do we mock TCP (Java Socket API) calls? Couldn't find a complete example as how it could be achieved in a Spring Boot Test & JUnit5 environment.

Title: Mockito for mocking TCP Calls


问:
Issue on mobile devices showing hidden Navbar menu on swiping
I have an issue with the navbar component in mobile devices. I've been following a react youtube tutorial and I have noticed that on mobile devices if I swipe to the left the navbar menu appears to be hidden in the right part of the screen, like if the screen is extended with the size of the menu. Moreover, when I open the menu and then I swipe I have the same issue, the screen is extended to the right the same size as the menu. I tried to solve it using the overflow-x: hidden; and transform: translateX but it does not work.

Here you can find an example. https://jsfiddle.net/jbacardit/5q7083hg/14/

How could avoid showing the hidden menu on the right on swiping to the left?

The css file

```<code>.navbar {
    width: 100%;
    height: 90px;
    top: 0;
    left: 0;
    background-color: #fff;
    border-bottom: 1px solid #eee;
}

.navbar .container {
    height: 100%;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding:1rem;
}

.navbar span {
    color: #5651e5;
}

.navbar .nav-menu {
    display: flex;
}

.navbar li {
    padding: 1rem;
}

.hamburger {
    display: none;
}

.navbar .icon {
    font-size: 1.5rem;
}

@media screen and (max-width:940px) {
    .hamburger {
        display: block;
    }

    .navbar .nav-menu {
        position: absolute;
        display: flex;
        flex-direction: column;
        align-items: center;
        top: 90px;
        right: -100%;
        height: 100%;
        width: 100%;
        background: rgba(255,255,255, .98);
        transition: 0.4s ease-in-out;
        z-index: 10;
    }

    .navbar .active {
        right: 0;
    }

    .navbar .nav-menu li a {
        font-size: 2rem;
    }
}
</code>```

This is the jsx file:

```<code>const { useState, useEffect } = React;

function Navbar() {
  const [click, setClick] = useState(false);
  const handleClick = () => setClick((prevState) => !prevState);

  return (
    <div className="navbar">
      <div className="container">
        <ul className={click ? 'nav-menu active' : 'nav-menu hideMe'}>
          <li><a href="#home">Home</a></li>
          <li><a href="#search">Search</a></li>
          <li><a href="#about">About</a></li>
          <li><a href="#contact">Contact</a></li>
        </ul>
        <div className="hamburger" onClick={handleClick}>
        {click ? (<i className="icon" >Click here</i>) : (<i className="icon">Swipe right =====></i>)}
        </div>
      </div>
    </div>
  );
}
</code>```

Body:
I have an issue with the navbar component in mobile devices. I've been following a react youtube tutorial and I have noticed that on mobile devices if I swipe to the left the navbar menu appears to be hidden in the right part of the screen, like if the screen is extended with the size of the menu. Moreover, when I open the menu and then I swipe I have the same issue, the screen is extended to the right the same size as the menu. I tried to solve it using the overflow-x: hidden; and transform: translateX but it does not work.

Here you can find an example. https://jsfiddle.net/jbacardit/5q7083hg/14/

How could avoid showing the hidden menu on the right on swiping to the left?

The css file

.navbar {
    width: 100%;
    height: 90px;
    top: 0;
    left: 0;
    background-color: #fff;
    border-bottom: 1px solid #eee;
}

.navbar .container {
    height: 100%;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding:1rem;
}

.navbar span {
    color: #5651e5;
}

.navbar .nav-menu {
    display: flex;
}

.navbar li {
    padding: 1rem;
}

.hamburger {
    display: none;
}

.navbar .icon {
    font-size: 1.5rem;
}

@media screen and (max-width:940px) {
    .hamburger {
        display: block;
    }

    .navbar .nav-menu {
        position: absolute;
        display: flex;
        flex-direction: column;
        align-items: center;
        top: 90px;
        right: -100%;
        height: 100%;
        width: 100%;
        background: rgba(255,255,255, .98);
        transition: 0.4s ease-in-out;
        z-index: 10;
    }

    .navbar .active {
        right: 0;
    }

    .navbar .nav-menu li a {
        font-size: 2rem;
    }
}

This is the jsx file:

const { useState, useEffect } = React;

function Navbar() {
  const [click, setClick] = useState(false);
  const handleClick = () => setClick((prevState) => !prevState);

  return (

Home

Search

About

Contact

        {click ? (Click here) : (Swipe right =====>)}

  );
}


问:
How to generate an image using System.Drawing in .net core
I feel like this question should have been answered like dozens of times but I'm blind to find one.

I would like to generate an image using System.Drawing and without using Bitmap (only Windows apparently) for a .NET Core WEBAPI. So something like

```<code>var rectangle = new Rectangle(100,100,23,34);
rectangle.ToImage()???
</code>```

Body:
I feel like this question should have been answered like dozens of times but I'm blind to find one.

I would like to generate an image using System.Drawing and without using Bitmap (only Windows apparently) for a .NET Core WEBAPI. So something like

var rectangle = new Rectangle(100,100,23,34);
rectangle.ToImage()???


问:
Getting error while running "superset re-encrypt-secrets" in superset
```<code>from superset.app import create_app
  File "C:\Users\delli\AppData\Local\Programs\Python\Python39\lib\site-packages\superset\app.py", line 29, in <module>
    from superset.extensions import (
ImportError: cannot import name 'jinja_context_manager' from 'superset.extensions' (C:\Users\delli\AppData\Local\Programs\Python\Python39\lib\site-packages\superset\extensions\__init__.py)
</code>```

I am using Flask verion 2.1.0.
Updated the secret key in  superset_config.py and tried to run "superset re-encrypt-secrets" command. Then getting import error for 'jinja_context_manager'.

I have tried downgrade the version of flask and pandas. But did not get resolved.

Body:
from superset.app import create_app
  File "C:\Users\delli\AppData\Local\Programs\Python\Python39\lib\site-packages\superset\app.py", line 29, in <module>
    from superset.extensions import (
ImportError: cannot import name 'jinja_context_manager' from 'superset.extensions' (C:\Users\delli\AppData\Local\Programs\Python\Python39\lib\site-packages\superset\extensions\__init__.py)

I am using Flask verion 2.1.0.
Updated the secret key in  superset_config.py and tried to run "superset re-encrypt-secrets" command. Then getting import error for 'jinja_context_manager'.

I have tried downgrade the version of flask and pandas. But did not get resolved.


问:
multithread bucket sort in java
I did the bucket sort in multithread mode in Java and these are running but the execution time of multiple threads is not good at all compared to single thread, is this normal or is there something wrong in the codes?

its my bucket sort code:

```<code>public void bucketSortMT(int[] A) {

    if (availableThreads >= 2) {

        int max = A[0];
        for(int i = 0; i < A.length; i++)
            if(max<A[i])max = A[i];

        int bucket[] = new int[max+1];

        for(int i = 0; i < A.length; i++)
            bucket[A[i]]++;

        int current = 0;
        for(int i = 0; i < bucket.length; i++){
            for (int j=0; j<bucket[i]; j++)
                A[current++]=i;
        }

        BucketSort bRight = new BucketSort(A, 0 , (A.length/2)-1 , availableThreads - 1);
        BucketSort bLeft = new BucketSort(A,  A.length/2 ,  A.length-1 , availableThreads - 1);
        bRight.start();
        bLeft.start();

        try {
            bRight.join();
            bLeft.join();
        } catch (InterruptedException e) {
        }
    } else {

    }

}
</code>```

In the same way I did merge sort and it worked fine its my main code:

```<code>public class Main {
    public static void main(String[] args) {

        Scanner scan = new Scanner(System.in);
        System.out.print("Enter The Size of Array: ");
        int n = scan.nextInt();
        Random rand = new Random();
        int[] numbers = new int[n];

int availableThreads = getRuntime().availableProcessors();

for (int i = 0; i < numbers.length; i++) {
    int value = rand.nextInt(10000000);

    numbers[i]=value;

}

BucketSort bucketSort1 = new BucketSort(numbers,0 , numbers.length-1, availableThreads);
long bucket_begin1 = System.nanoTime();
bucketSort1.run();
long bucket_end1 = System.nanoTime();
float bucket_time1 = (bucket_end1-bucket_begin1)/1000000.0f;
System.out.println("\nBucket Sorting Time Using " + availableThreads  + bucket_time1 + "  milli seconds");
</code>```

Title: multithread bucket sort in java

Body:
I did the bucket sort in multithread mode in Java and these are running but the execution time of multiple threads is not good at all compared to single thread, is this normal or is there something wrong in the codes?

its my bucket sort code:

public void bucketSortMT(int[] A) {

    if (availableThreads >= 2) {

        int max = A[0];
        for(int i = 0; i < A.length; i++)
            if(max<A[i])max = A[i];

        int bucket[] = new int[max+1];

        for(int i = 0; i < A.length; i++)
            bucket[A[i]]++;

        int current = 0;
        for(int i = 0; i < bucket.length; i++){
            for (int j=0; j<bucket[i]; j++)
                A[current++]=i;
        }

        BucketSort bRight = new BucketSort(A, 0 , (A.length/2)-1 , availableThreads - 1);
        BucketSort bLeft = new BucketSort(A,  A.length/2 ,  A.length-1 , availableThreads - 1);
        bRight.start();
        bLeft.start();

        try {
            bRight.join();
            bLeft.join();
        } catch (InterruptedException e) {
        }
    } else {

    }

}

In the same way I did merge sort and it worked fine its my main code:

public class Main {
    public static void main(String[] args) {

        Scanner scan = new Scanner(System.in);
        System.out.print("Enter The Size of Array: ");
        int n = scan.nextInt();
        Random rand = new Random();
        int[] numbers = new int[n];

int availableThreads = getRuntime().availableProcessors();

for (int i = 0; i < numbers.length; i++) {
    int value = rand.nextInt(10000000);

    numbers[i]=value;

}

BucketSort bucketSort1 = new BucketSort(numbers,0 , numbers.length-1, availableThreads);
long bucket_begin1 = System.nanoTime();
bucketSort1.run();
long bucket_end1 = System.nanoTime();
float bucket_time1 = (bucket_end1-bucket_begin1)/1000000.0f;
System.out.println("\nBucket Sorting Time Using " + availableThreads  + bucket_time1 + "  milli seconds");


问:
Series object has no attribute 'merge'
When i am calling a function using apply function and store into one variable that variable will become series. When merging those variable it says Series object has no attribute 'merge' After that have converted into dataframe and got unhashable type: 'DataFrame' error.
i want to merge those df's.

Code which i am running:

```<code>def src_aggregated_input(columnname, tablename):
    try:
        df_src1["column_name"] = df_src1["column_name"].replace('', np.nan, regex=True)
        if df_src1["column_name"].isnull().values.any():
            df_agg_src = pd.DataFrame(columns=['src_agg_cnt'])
            return df_agg_src
        sql = 'SELECT COUNT(' + columnname + ') AS src_agg_cnt,' + columnname + ' FROM ' + \
              tablename + ' group by ' + columnname
        #sql = sql[0]
        loging(datetime.datetime.now(), '-agg src sql', sql)
        df_agg_src = pd.read_sql_query(sql, db_conn)
        print("df_agg_src",df_agg_src)
        print("src",type(df_agg_src))
        return df_agg_src

    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
        loging(datetime.datetime.now(), 'src_agg', sys.exc_info()[1])
        return np.nan
</code>```

Above function output:

```<code>df_agg_src       src_agg_cnt  Acct_id
0               2  DAI0001
1               2  DAI0002
2               2  DAI0003
3               2  DAI0004
4               2  DAI0005
...           ...      ...
996             1  DAI0997
997             1  DAI0998
998             1  DAI0999
999             2  DAI1000
1000            1  DAI1001

[1001 rows x 2 columns]
src <class 'pandas.core.frame.DataFrame'>
df_agg_src    src_agg_cnt cust_code
0            1      C001
1            2      C003
2            1      C012
3            1      C345
4            2      C234
5            1      C743
6            1      C456
src <class 'pandas.core.frame.DataFrame'>

</code>```

df_src1 dataframe output:

```<code>
df_src1       table_name column_name
0  banking_fraud     Acct_id
1      sale_mast   cust_code

</code>```

Function call:

```<code>df_src2 = df_src1.apply(lambda x: src_aggregated_input(x['column_name'], x['schema_table']), axis=1)#series error

#Convert to dataframe
df_src2 = df_src1.apply(lambda x: src_aggregated_input(x['column_name'], x['schema_table']), axis=1).to_frame() #output/type of src_aggregated_input function is dataframe

def aggregated_cnt_check():
    try:
        df_agg_merge = df_src2.merge(df_tgt2,   #error in merging part
                                   indicator=True,
                                   how='outer')
        return df_agg_diff
</code>```

output of df_src2:

```<code>type <class 'pandas.core.frame.DataFrame'>
**df_src2**                                                    0
0        src_agg_cnt  Acct_id
0               2  ...
1     src_agg_cnt cust_code
0            1      C...

</code>```

Please suggest how to handle this scenario.

Title: Series object has no attribute 'merge'

Body:
When i am calling a function using apply function and store into one variable that variable will become series. When merging those variable it says Series object has no attribute 'merge' After that have converted into dataframe and got unhashable type: 'DataFrame' error.
i want to merge those df's.

Code which i am running:

def src_aggregated_input(columnname, tablename):
    try:
        df_src1["column_name"] = df_src1["column_name"].replace('', np.nan, regex=True)
        if df_src1["column_name"].isnull().values.any():
            df_agg_src = pd.DataFrame(columns=['src_agg_cnt'])
            return df_agg_src
        sql = 'SELECT COUNT(' + columnname + ') AS src_agg_cnt,' + columnname + ' FROM ' + \
              tablename + ' group by ' + columnname
        #sql = sql[0]
        loging(datetime.datetime.now(), '-agg src sql', sql)
        df_agg_src = pd.read_sql_query(sql, db_conn)
        print("df_agg_src",df_agg_src)
        print("src",type(df_agg_src))
        return df_agg_src

    except Exception as e:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
        loging(datetime.datetime.now(), 'src_agg', sys.exc_info()[1])
        return np.nan

Above function output:

df_agg_src       src_agg_cnt  Acct_id
0               2  DAI0001
1               2  DAI0002
2               2  DAI0003
3               2  DAI0004
4               2  DAI0005
...           ...      ...
996             1  DAI0997
997             1  DAI0998
998             1  DAI0999
999             2  DAI1000
1000            1  DAI1001

[1001 rows x 2 columns]
src <class 'pandas.core.frame.DataFrame'>
df_agg_src    src_agg_cnt cust_code
0            1      C001
1            2      C003
2            1      C012
3            1      C345
4            2      C234
5            1      C743
6            1      C456
src <class 'pandas.core.frame.DataFrame'>

df_src1 dataframe output:

df_src1       table_name column_name
0  banking_fraud     Acct_id
1      sale_mast   cust_code

Function call:

df_src2 = df_src1.apply(lambda x: src_aggregated_input(x['column_name'], x['schema_table']), axis=1)#series error

#Convert to dataframe
df_src2 = df_src1.apply(lambda x: src_aggregated_input(x['column_name'], x['schema_table']), axis=1).to_frame() #output/type of src_aggregated_input function is dataframe

def aggregated_cnt_check():
    try:
        df_agg_merge = df_src2.merge(df_tgt2,   #error in merging part
                                   indicator=True,
                                   how='outer')
        return df_agg_diff

output of df_src2:

type <class 'pandas.core.frame.DataFrame'>
**df_src2**                                                    0
0        src_agg_cnt  Acct_id
0               2  ...
1     src_agg_cnt cust_code
0            1      C...

Please suggest how to handle this scenario.


问:
Log metrics in Springboot applicaiton using LoggingMeterRegistry
I have some metrics being created in my springboot application and want to log the details of the metrics in a specific format as below:
2018-07-06 17:00:28,884 [metrics-logger-reporter-thread-1] [INFO] (com.codahale.metrics.Slf4jReporter) type=METER, name=io.dropwizard.jetty.MutableServletContextHandler.async-timeouts, count=0, mean_rate=0.0, m1=0.0, m5=0.0, m15=0.0, rate_unit=events/second

I'm currently using LoggingMeterRegistry to log my metrics but the format they get printed it is:system.cpu.usage{} value=0.041922","logger_name":"io.micrometer.core.instrument.logging.LoggingMeterRegistry"

I know that the required format can be achieved through codahale.dropwizard metrics but i want the same using LoggingMeterRegistry from "micrometer" since thats what i am using to calculate my other metrics.

Any help?


问:
Azure API Management CSRF Policy
I'm trying to create an inbound policy to pass my x-csrf-token to a Post method. However, when i check the tracing, i'm getting null value for the x-csrf-token.
I'm using the snippet given here in the https://github.com/Azure/api-management-policy-snippets/blob/master/examples/Get%20X-CSRF%20token%20from%20SAP%20gateway%20using%20send%20request.policy.xml.

Have anyone come across this issue before?

<policies>
    <inbound>
        <base />
        <authentication-basic username="{{SAP-test-user}}" password="{{SAP-test-PW}}" />
        <set-variable name="checkRequestUrl" value="@(context.Request.Url.ToString())" />
        <rewrite-uri template="/" />
        <choose>

            <when condition="@(context.Request.Method != "GET" && context.Request.Method != "HEAD")">

                <send-request mode="new" response-variable-name="SAPCSRFToken" timeout="10" ignore-error="false">
                    <set-url>@(context.Request.Url.ToString())</set-url>
                    <set-method>HEAD</set-method>
                    <set-header name="X-CSRF-Token" exists-action="override">
                        <value>Fetch</value>
                    </set-header>
                    <set-header name="Authorization" exists-action="override">
                        <value>@(context.Request.Headers.GetValueOrDefault("Authorization"))</value>
                    </set-header>
                </send-request>

                <choose>
                    <when condition="@(((IResponse)context.Variables["SAPCSRFToken"]).StatusCode == 200)">
                        <set-header name="X-CSRF-Token" exists-action="override">
                            <value>@(((IResponse)context.Variables["SAPCSRFToken"]).Headers.GetValueOrDefault("x-csrf-token"))</value>
                        </set-header>
                        <set-header name="Cookie" exists-action="override">
                            <value>@{
                    string rawcookie = ((IResponse)context.Variables["SAPCSRFToken"]).Headers.GetValueOrDefault("Set-Cookie");
                    string[] cookies = rawcookie.Split(';');
                                /* new session sends a XSRF cookie */
                    string xsrftoken = cookies.FirstOrDefault( ss => ss.Contains("sap-XSRF"));
                                /* existing sessions sends a SessionID. No other cases anticipated at this point. Please create a GitHub Pull-Request if you encounter uncovered settings. */
                                if(xsrftoken == null){
                                    xsrftoken = cookies.FirstOrDefault( ss => ss.Contains("SAP_SESSIONID"));
                                }

                    return xsrftoken.Split(',')[1];}</value>
                        </set-header>
                    </when>
                </choose>
            </when>
        </choose>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>```

Title: Azure API Management CSRF Policy


问:
Is there a VS Code settings or plugin for suggesting file path of CSS files (css, scss, less, etc.) when importing in ReactJS/Next?
Whenever you want to import a js/ts file in a js file, you will always have this path suggestor like this.

But there is none for SCSS or other CSS file types. As you can see there is a scss file in the same directory but VSCode didn't suggest it for me (we can not export SCSS from JS but the image just for example, VSCode didn't suggest for me on import either).
My folder already has 1 scss file.

Is there any setting or plugin that can help me with this that I may accidentally skip when finding for one in Settings and Extensions? Thanks.

I'm expecting it to auto suggest path/file like the above image.


问:
Creating A custom map of an internal structure
I got a project idea but I need to create custom maps of some specific buildings, get user location within the building and give directions like bathroom location from their current location within the building. What language could I use? how could I do that? what resources could help me accomplish this project.

I was considering using the phone camera feature, but how do I account for elevation-like change in floor levels within the building

Please,any suggestions?

Thanks in advance


问:
Series Data is not rendered in echarts vue 3
am look to answer this bug on Apache Echarts with vue 3 Composition API
am using apache echarts for rendering  maps as a background, the maps is become from GeoJSON data of province accross my country : Source GeoJSON, the rendering process of GeoJson was successfuly as expected, but take a this code bellow, Here is problems occurs, am expected that after rendering the chart, the series that was defined is expect rendered also, but there is not yet, so whats am wrong? FYi : am need to rendr the chart and make tooltip of each province section of chart series (simplify Chloropeth Mapping), am following many guide but there is not works yet. am also referring of the official documentation of apache echart example her Chloropet Apacghe Echarts, but not working as expeccted. so is there can give me the suggestion of am wrong ? great thanks for all, looking best oppinions and suggestion from you here is my result that is not expected :
just rendered maps, not the defined series
and here is my expectation(same as example) : Expected the series is rendered in maps section and if am hovered my cursor the tooltip is show the data value of the given series;

Apache Echart COnfiguration in Vue (as reactive)

```<code>          title: {
            text: 'Peta Sebaran Arsiparis （2022）',
            subtext: 'Open source data',
          },
          toolbox: {
            show: true,
            orient: 'vertical',
            left: 'right',
            top: 'center',
            feature: {
              dataView: { readOnly: false },
              restore: {},
              saveAsImage: {}
            }
          },
          tooltip: {
            trigger: 'item',
            showDelay: 0,
            transitionDuration: 0.2
          },
          geo: {
            map: "indonesia-province",
            roam: true,
            nameProperty: "Propinsi",
            tooltip: {
              show: true
            },
            itemStyle: {
              color: '#fff'
            },
            emphasis: {
              itemStyle: {
                color: undefined,
                borderColor: 'green',
                borderWidth: 2
              },
              label: {
                show: false
              }
            },
            select: {
              itemStyle: {
                color: 'green'
              },
              label: {
                show: false,
                textBorderColor: '#fff',
                textBorderWidth: 2
              }
            },
            regions: generateRegions(provinceNames)
          },
          visualMap: {
            min: 800,
            max: 50000,
            text: ['High', 'Low'],
            realtime: false,
            calculable: true,
            inRange: {
              color: ['lightskyblue', 'yellow', 'orangered']
            }
          },
          series: [
            { // 地图配置
              name: 'Province daatatasdbashdvjk',
              type: 'map',
              map: 'indonesia-province', // 自定义扩展图表类型
              nameProperty: "Propinsi",
              geoIndex: 0,
              data: generateMapData(provinceNames)
            }
          ],
        }
</code>```

Body:
am look to answer this bug on Apache Echarts with vue 3 Composition API
am using apache echarts for rendering  maps as a background, the maps is become from GeoJSON data of province accross my country : Source GeoJSON, the rendering process of GeoJson was successfuly as expected, but take a this code bellow, Here is problems occurs, am expected that after rendering the chart, the series that was defined is expect rendered also, but there is not yet, so whats am wrong? FYi : am need to rendr the chart and make tooltip of each province section of chart series (simplify Chloropeth Mapping), am following many guide but there is not works yet. am also referring of the official documentation of apache echart example her Chloropet Apacghe Echarts, but not working as expeccted. so is there can give me the suggestion of am wrong ? great thanks for all, looking best oppinions and suggestion from you here is my result that is not expected :
just rendered maps, not the defined series
and here is my expectation(same as example) : Expected the series is rendered in maps section and if am hovered my cursor the tooltip is show the data value of the given series;

Apache Echart COnfiguration in Vue (as reactive)

          title: {
            text: 'Peta Sebaran Arsiparis （2022）',
            subtext: 'Open source data',
          },
          toolbox: {
            show: true,
            orient: 'vertical',
            left: 'right',
            top: 'center',
            feature: {
              dataView: { readOnly: false },
              restore: {},
              saveAsImage: {}
            }
          },
          tooltip: {
            trigger: 'item',
            showDelay: 0,
            transitionDuration: 0.2
          },
          geo: {
            map: "indonesia-province",
            roam: true,
            nameProperty: "Propinsi",
            tooltip: {
              show: true
            },
            itemStyle: {
              color: '#fff'
            },
            emphasis: {
              itemStyle: {
                color: undefined,
                borderColor: 'green',
                borderWidth: 2
              },
              label: {
                show: false
              }
            },
            select: {
              itemStyle: {
                color: 'green'
              },
              label: {
                show: false,
                textBorderColor: '#fff',
                textBorderWidth: 2
              }
            },
            regions: generateRegions(provinceNames)
          },
          visualMap: {
            min: 800,
            max: 50000,
            text: ['High', 'Low'],
            realtime: false,
            calculable: true,
            inRange: {
              color: ['lightskyblue', 'yellow', 'orangered']
            }
          },
          series: [
            { // 地图配置
              name: 'Province daatatasdbashdvjk',
              type: 'map',
              map: 'indonesia-province', // 自定义扩展图表类型
              nameProperty: "Propinsi",
              geoIndex: 0,
              data: generateMapData(provinceNames)
            }
          ],
        }


问:
Using Rsync, backup Chromebook and server folders
A folder on my Chromebook that is synced with the server is what I want. I want to create "cloned" folders on my Chromebook and server. When altering files using rsync on a Chromebook or server, both directories will be updated. I'd appreciate some pointers on how to use the rsync command to accomplish this.

Maybe this would work:

from Chromebook to server.

rsync -av /Volumes/NewHDD1_DATA/Projects_archive_Small bernardo@128.139.17.11:/home/bernardo/Projects_archive_Small

from server to Chromebook

rsync -av /home/bernardo/Projects_archive_Small/Projects_archive_Small bernardo@dhcp17-207.agri.huji.ac.il:/Volumes/NewHDD1_DATA/

I also want to delete old files from local or remote locations. Perhaps there is a superior choice to rsync.


问:
Using expression to Display a object field value into Salesforce Hero
is there a way to display a object field value(rather than recordId and recordName) into a Hero in Salesforce, I wanna display the caseNumber, but it's not converting into the expected result.
enter image description hereenter image description here

I tried, other expression formats, and also created a aura component to display the caseNumber into Hero, but realized that it cannot be dragged into the Hero


问:
Showing "Sorry, Something went wrong" message while try to login facebook through react native application

As you can see in the screenshot above, I got the warning message when I added "user_friends" to loginButton.setPermissions("email", "public_profile", "user_friends"), but when I tried logging into Facebook, I received a message saying, "Sorry, something went wrong." Is this a permission disable issue or not?

It has been over a year since I submitted the app and there were no issues. However, it is one month before the issue begins.

React native package used is : react-native-fbsdk-next


问:
Cannot call show method in UnityAds Using SwiftUi
I am trying to show unity ads in my ios project. I am using SwiftUI (Not AppDelegate, not Storyboard). There are not much examples on the web, and the little of them there are old and does not support showing ads with swiftui. Even the unity documentation website does not support it yet. please help me, I get this error from my show ads method and the code won't build: Cannot convert value of type 'UIViewController.Type' to expected argument type 'UIViewController'

```<code>import SwiftUI
import UnityAds

//Initialize Unity ads here
UnityAds.initialize("307659", testMode: true)

func loadInterstitial_UnityAds(){
    if UnityAds.isInitialized(){
        UnityAds.load("video")
    }
}
func showAds_Unity(){
    UnityAds.show(UIViewController, placementId:"307659", showDelegate: nil)
}
</code>```

Body:
I am trying to show unity ads in my ios project. I am using SwiftUI (Not AppDelegate, not Storyboard). There are not much examples on the web, and the little of them there are old and does not support showing ads with swiftui. Even the unity documentation website does not support it yet. please help me, I get this error from my show ads method and the code won't build: Cannot convert value of type 'UIViewController.Type' to expected argument type 'UIViewController'

import SwiftUI
import UnityAds

//Initialize Unity ads here
UnityAds.initialize("307659", testMode: true)

func loadInterstitial_UnityAds(){
    if UnityAds.isInitialized(){
        UnityAds.load("video")
    }
}
func showAds_Unity(){
    UnityAds.show(UIViewController, placementId:"307659", showDelegate: nil)
}


问:
React Google Maps
I am trying to use @react-google-maps/api in my React JS application. The first issue is that the documentation is outdated I know this because for the latest version of React to use Marker you have to import MarkerF, took me  a while to have that working. I am now trying to implement MarkerClusterer and I am struggling.

```<code>  <GoogleMap zoom={15} center={center} mapContainerStyle={containerStyle}>
    <MarkerClusterer
    minimumClusterSize={5}>
      {(clusterer) =>
        locations.map((location) => (
          <MarkerF
        key={createKey(location)}
        position={location}
        clusterer={clusterer}
        icon={"https://img.icons8.com/color/48/000000/map-pin.png"}/>
          ))
      }
    </MarkerClusterer>
  </GoogleMap>
</code>```

I have this code and I am getting an error

No overload matches this call.
Overload 1 of 2, '(props: MarkerClustererProps | Readonly): ClustererComponent', gave the following error.
Type 'Element[]' is missing the following properties from type 'ReactElement<any, any>': type, props, key
Overload 2 of 2, '(props: MarkerClustererProps, context: any): ClustererComponent', gave the following error.
Type 'Element[]' is not assignable to type 'Element'.

This is the example from the documentation and it is not working. What am I not doing correctly? Document is here

Title: React Google Maps

Body:
I am trying to use @react-google-maps/api in my React JS application. The first issue is that the documentation is outdated I know this because for the latest version of React to use Marker you have to import MarkerF, took me  a while to have that working. I am now trying to implement MarkerClusterer and I am struggling.

  <GoogleMap zoom={15} center={center} mapContainerStyle={containerStyle}>
    <MarkerClusterer
    minimumClusterSize={5}>
      {(clusterer) =>
        locations.map((location) => (
          <MarkerF
        key={createKey(location)}
        position={location}
        clusterer={clusterer}
        icon={"https://img.icons8.com/color/48/000000/map-pin.png"}/>
          ))
      }
    </MarkerClusterer>
  </GoogleMap>

I have this code and I am getting an error

No overload matches this call.
Overload 1 of 2, '(props: MarkerClustererProps | Readonly): ClustererComponent', gave the following error.
Type 'Element[]' is missing the following properties from type 'ReactElement<any, any>': type, props, key
Overload 2 of 2, '(props: MarkerClustererProps, context: any): ClustererComponent', gave the following error.
Type 'Element[]' is not assignable to type 'Element'.

This is the example from the documentation and it is not working. What am I not doing correctly? Document is here