I have this blob in the middle of the screen, and when the user moves the mouse, the blob moves along. I'm trying to limit that movement. I want my blob to move only 30px to the left/right/bottom/top. Is it possible? Here is my code:
xposition = pmouseX === 0 ? windowWidth/2 : pmouseX
yposition = pmouseY === 0 ? windowHeight/2: pmouseY
Thanks!
There are 2 ways that come to my mind:
You can map your width and height to -30px ...30px
let xpos = map(mouseX, 0, width, width/2-30, width/2+30);
You can just do:
xpos = Math.floor(windowWidth/2-mouseX) > 30 ? windowWidth/2 : mouseX
This should work with both pmouseX and mouseX but I'm curious, why are you using pmouseX instead of current frame mouseX?
You can limit the values with min() and max() functions:
xposition = pmouseX === 0 ? windowWidth/2 : max(min(pmouseX,30),-30)
yposition = pmouseY === 0 ? windowHeight/2: max(min(pmouseY,30),-30)
or with constrain() function:
xposition = pmouseX === 0 ? windowWidth/2 : constrain(pmouseX, -30, 30)
yposition = pmouseY === 0 ? windowHeight/2: constrain(pmouseY, -30, 30)
Related
I use the following code to return an NSRectangle
let ciimage = ciImage.cropped(to: $0.bounds.insetBy(dx: -$0.bounds.width/1.6, dy: -$0.bounds.width/1.6) )
But the returned rectangle has unequal width and height.How can i make it a square?
let width = $0.bounds.width; let height = $0.bounds.height
let widthInset = (width > height) ? (width - height) / 2 : 0
let heightInset = (height > width) ? (height - width) / 2 : 0
let croppedBounds = $0.bounds.insetBy(dx: widthInset, dy: heightInset)
ciImage = ciImage.cropped(to: croppedBounds)
Something like that?
I'm working on a project using D3js V5 that takes the input of a CSV file and returns a Workflow diagram, everything is working fine besides on it's own.
My problem is when I fit the workflow, through a Fit Button, and after that I use the mouse wheel to zoom in or out it just jumps to the previous zoom and position settings.
After some research I've found that after D3v4+ that "Zoom behaviours no longer store the active zoom transform (i.e., the visible region; the scale and translate) internally. The zoom transform is now stored on any elements to which the zoom behaviour has been applied.(link)"
That being said I cannot make it work and that's why I'm asking for your help.
The code is has follows:
document.getElementById('fitBTN').addEventListener('click', zoomFit);
function zoomFit() {
let bounds = document.getElementById('svgContent').getBBox();
let parent = document.getElementById('svgContent').parentElement;
let fullWidth = parent.clientWidth,
fullHeight = parent.clientHeight;
let width = bounds.width,
height = bounds.height;
let midX = bounds.x + width / 2,
midY = bounds.y + height / 2;
if (width == 0 || height == 0) return; // nothing to fit
let scale = 0.95 / Math.max(width / fullWidth, height / fullHeight);
let translate = [
fullWidth / 2 - scale * midX,
fullHeight / 2 - scale * midY
];
document
.getElementById('svgContent')
.setAttribute(
'transform',
'translate(' +
translate[0] +
',' +
translate[1] +
') scale(' +
scale +
')'
);
}
svg
.call(
zoom()
.on('zoom', () => {
document
.getElementById('svgContent')
.setAttribute(
'transform',
'translate(' +
currentEvent.transform.x * 0.125 +
',' +
currentEvent.transform.y * 0.125 +
') scale(' +
currentEvent.transform.k +
')'
);
})
.scaleExtent([0.1, 1])
)
.on('dblclick.zoom', false)
.on('wheel', function() {
currentEvent.preventDefault();
})
.on('wheel', false);
I believe that I have to had some variable that is able to read the state of the transform translate, but how?
So the answer provided by #AndrewReid has helped me resolve my issue and the corrected version of the code is here:
function zoomFit() {
let bounds = document.getElementById('svgContent').getBBox();
let parent = document.getElementById('svgContent').parentElement;
let fullWidth = parent.clientWidth,
fullHeight = parent.clientHeight;
let width = bounds.width,
height = bounds.height;
let midX = bounds.x + width / 2,
midY = bounds.y + height / 2;
if (width == 0 || height == 0) return; // nothing to fit
let scale = 0.95 / Math.max(width / fullWidth, height / fullHeight);
let translate = [
fullWidth / 2 - scale * midX,
fullHeight / 2 - scale * midY
];
document
.getElementById('svgContent')
.setAttribute(
'transform',
'translate(' +
translate[0] +
',' +
translate[1] +
') scale(' +
scale +
')'
);
// Create a zoom transform from d3.zoomIdentity
var transform = zoomIdentity
.scale(scale)
.translate(-translate[0], -translate[1]);
// Apply the zoom and trigger a zoom event:
svg.call(zoom().transform, transform);
}
var zooming = zoom()
.scaleExtent([0.1, 1])
.translateExtent([[0, 0], [840, 740]])
.on('zoom', zoomed);
svg.call(zooming);
function zoomed() {
svg
.attr('transform', currentEvent.transform)
.on('dblclick.zoom', false)
.on('wheel', function() {
currentEvent.preventDefault();
});
}
But another issue got in the way which is the panning function was lost.
I'll have to figure that one out and I'll update this answer has soon has the solutions is found.
Best regards,
I am using SVG.js and jquery to develop a simple yacht racing SVG animation to simulate a yacht race. I can easily animate an image [yacht icon] along the path. But I also want the yacht to rotate or the yacht heading change as the yacht travels up the path/route. I have tried a view things but cannot get it working. please help!
i am using this code..
function move_yacht_new(route,yacht,score){
var route1 = draw.path('M 535.07931,510.0164 C 594.9314,509.34072 667.14382,469.54596 691.80372,382.84271');
route1.fill('none');
var length = route1.length();
var y_pos = score;
var sailAngle = 90;
var currentRotation;
route1.hide();
var text = draw.text(function(add) {
add.tspan('We go ')
add.tspan('up').fill('#f09').dy(-40)
add.tspan(', then we go down, then up again').dy(40)
})
var image = draw.image('../globals/game/images/' + yacht + '-yacht.png',20, 20).id('yacht_' + yacht);
var scorePerc = (length/100) * (score);
//vdiscountPerc = calcPerc.toFixed();
var text = draw.text(yacht + ' (' + Math.round(score) + ')');
image.animate(5000, '<>').during(function(pos, morph, eased){
var p = route1.pointAt(eased * scorePerc);
image.move(p.x, p.y);
text.move(p.x, p.y).font({ fill: '#fff', size: 5, family: 'Helvetica', leading: '1.5em' });
var coord = image.bbox();
var center = coord.x + (coord.width/2) + ' '+ coord.y + (coord.height/2);
console.log('center ' + center);
var x_coord = image.attr('x');
var y_coord = image.attr('y');
//console.log(x_coord + ',' + y_coord);
image.rotate(-45, coord.x + (coord.width/2), coord.y + (coord.height/2));
var angle = Math.atan2(p.y, p.x) * 180 / Math.PI;//angle for tangent
//Shifting center to center of rocket
var centerX = p.x - 24,
centerY = p.y - 12;
console.log('angle > ' + angle);
//}).loop(true, true)
})
}
Blockquote
But this rotates the icons away from the path in a wrong direction.
I managed to resolve this using animation.js script.
Add the yacht icon into a group, translate the group along the path and rotate the yacht icon in the group around the group origin:
var g = draw.group()
var yacht = g.image(yachtUrl, width, height).center(0,0)
// in animate function:
g.transform(x: x, y: y)
yacht.transform(rotation: degrees, cx: 0, cy: 0)
here is how my link draw currently.
here is below picture code (that comes from my real putout html)
<svg height="1210" width="1400">
<path class="link" id="linkId_2" opacity="0.9468531468531468" style="stroke-width: 5px; marker-end: url(#end-arrow);" d="M652.3404429062306,276.08144057675605A166.53959040529506,166.53959040529506 0 0,1 767.3217566577334,315.4663301140565"></path>
</svg>
But I want to draw like this. (should be like link, not part of circle)
here is my real part of code.
function updateLink() {
this.attr('d', function(d) {
var deltaX = d.target.x - d.source.x,
deltaY = d.target.y - d.source.y,
dist = Math.sqrt(deltaX * deltaX + deltaY * deltaY),
normX = deltaX / dist,
normY = deltaY / dist;
if( !normX) normX = 0;
if( !normY) normY = 0;
var sourcePadding = d.left ? circleSize(d.source.inDegree) + 10 : 20,
targetPadding = d.right ? circleSize(d.target.inDegree) + 5 : 20,
sourceX = d.source.x + (sourcePadding * normX),
sourceY = d.source.y + (sourcePadding * normY),
targetX = d.target.x - (targetPadding * normX),
targetY = d.target.y - (targetPadding * normY);
return "M" + sourceX + "," + sourceY + "A" + dist + "," + dist + " 0 0,1 " + targetX + "," + targetY;
});
}
Here is example I used (http://bl.ocks.org/mbostock/1153292)
If you want the stroke to be unfilled then simply set the fill to none and the stroke to a colour e.g.
<svg height="1210" width="1400" viewBox="600 230 600 600">
<path class="link" id="linkId_2" opacity="0.9468531468531468" style="fill:none;stroke:black;stroke-width: 5px; marker-end: url(#end-arrow);" d="M652.3404429062306,276.08144057675605A166.53959040529506,166.53959040529506 0 0,1 767.3217566577334,315.4663301140565"></path>
</svg>
Okay, so for an assignment I have to make a function crop() that will crop a picture in test_crop(). Here's the code.
def crop(pict, startX, startY, endX, endY):
width = endX - startX + 1
height = endY - startY + 1
canvas = makeEmptyPicture(width, height)
targetX = 100
for sourceX in range(45,200):
targetY = 100
for sourceY in range(25,200):
color = getColor(getPixel(pict, sourceX, sourceY))
setColor(getPixel(canvas, targetX, targetY), color)
targetY = targetY + 1
targetX = targetX + 1
show(pict)
show(canvas)
return canvas
def test_crop():
setMediaPath()
pict = makePicture("redMotorcycle.jpg")
croppedPict = crop(pict, 100, 100, 700, getHeight(pict)/2)
show(pict)
show(croppedPict)
The error occurs on this piece of code:
setColor(getPixel(canvas, targetX, targetY), color)
It says "Inappropriate argument (of correct type. An error occured attempting to pass an argument to a function."
Can someone please tell me what is wrong with it? It is the same code from the textbook.
This works. I cannot work out why you are getting that error, it may be in how you are getting your values for startX, startY, endX, endY in
def crop(pict, startX, startY, endX, endY):
def crop(pict):
width = getWidth(pict)
height = getHeight(pict)
canvas = makeEmptyPicture(width, height)
targetX = 100
for sourceX in range(45,200):
targetY = 100
for sourceY in range(25,200):
color = getColor(getPixel(pict, sourceX, sourceY))
setColor(getPixel(canvas, targetX, targetY),color)
targetY = targetY + 1
targetX = targetX + 1
show(pict)
show(canvas)
return canvas
The original image:
The cropped image:
This works, beyond this, you will need to provide more information about your code.