在这个草图中,对象'位置从固定点从左到右计算。放大或缩小时,对象也会从左向右放大或缩小。
如何计算我需要添加到x的偏移量,以便在放大或缩小对象时根据鼠标的X位置展开或缩小(因此mouseX将成为缩放的原点)?< / p>
草图的代码(需要一段时间才能加载,因为图像来自互联网)
PImage backgroundImage;
PFont font;
int x = 0;
int xoffset = 0;
int deltax = 5;
float scale = 512/30;
float deltascale = 0.02;
ArrayList<Object> ObjectList;
//String[] objectfile;
//String[] configfile;
//int savetimer = 0;
class Object {
String name;
float diameter;
String unit;
String sprite;
PImage img;
int wid;
int hei;
int xpos;
Object(String Oname, float Odiameter, String Ounit, String Oimg) {
name = Oname;
diameter = Odiameter;
unit = Ounit;
img = loadImage(Oimg);
sprite = Oimg;
//img = loadImage(Oimg);
wid = img.width;
hei = img.height;
}
}
void setup() {
size(1500, 800);
frameRate(200);
//objectfile = loadStrings("objects.txt");
//configfile = loadStrings("config.ini");
//backgroundImage = loadImage("background.png");
//font = createFont("Franklin Gothic Book Regular.ttf", 32);
fill(255,255,255);
textSize(32);
textAlign(CENTER, CENTER);
text("Images are loading (this may take a while)",700,400);
ObjectList = new ArrayList();
readObjects();
//readConfig();
//loadOffset();
}
void addObject(String Aname, float Adiameter, String Aunit, String Aimg) {
//if (Aimg.equals("null")) {
// ObjectList.add(new Object(Aname, Adiameter, Aunit, "images/"+Aname+".png"));
//} else {
ObjectList.add(new Object(Aname, Adiameter, Aunit, Aimg));
//}
}
void readObjects() {
//for (int i = 0; i < objectfile.length; i++) {
// String[] currentObject = split(objectfile[i], ",");
// addObject(currentObject[0], float(currentObject[1]), currentObject[2], currentObject[3]);
//}
addObject("RED", 30, "m", "https://s-media-cache-ak0.pinimg.com/736x/8f/1b/cc/8f1bcc72c81d1e9370597f7239ee476a.jpg");
//addObject("ORANGE", 60, "m", "http://6iee.com/data/uploads/36/489075.jpg");
addObject("YELLOW", 70, "m", "https://i.stack.imgur.com/aez1V.jpg");
addObject("GREEN", 100, "m", "http://space-facts.com/wp-content/uploads/mars.jpg");
addObject("PURPLE", 105, "m", "http://space-facts.com/wp-content/uploads/jupiter.png");
addObject("PINK", 110, "m", "https://vignette1.wikia.nocookie.net/starwars/images/4/4a/Alderaan.jpg");
addObject("BROWN", 150, "m", "https://cdn.pixabay.com/photo/2013/07/12/16/33/venus-151142_960_720.png");
addObject("GRAY", 180, "m", "http://www.lpi.usra.edu/lpi_40th/images/1989/neptune.jpg");
//addObject("WHITE", 200, "m", "http://www.clipartkid.com/images/19/log-in-sign-up-upload-clipart-Dpr48a-clipart.png");
addObject("INDIGO", 300, "m", "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a0/Sun_in_February.jpg/155px-Sun_in_February.jpg");
addObject("SKYBLUE", 301, "m", "https://upload.wikimedia.org/wikipedia/commons/e/ea/Uranus_(Edited).jpg");
addObject("BLUE", 1000, "m", "https://vignette2.wikia.nocookie.net/heman/images/3/36/Earth.jpg");
}
//void readConfig() {
// for (int i = 0; i < configfile.length; i++) {
// char slash = configfile[i].charAt(0);
// if (slash != '/') {
// //getting config values based on line number
// if (i == 1) {
// xoffset = int(configfile[i]);
// } else if (i == 3) {
// scale = float(configfile[i]);
// }
// }
// }
//}
void draw() {
//image(backgroundImage, 0, 0);
fill(0,0,0);
rect(0, 0, 1500, 800);
int x = 0 + xoffset;
for ( Object drawObject : ObjectList ) {
float dia = drawObject.diameter;
//int drawWidthh = int(scale * dia);
int drawWidth = int(scale * dia);
int drawHeight = int(drawWidth * drawObject.hei / drawObject.wid);
if (x+drawObject.img.width >= 0 && x <= 1500) {
//checks if image is too small to be drawn
if (drawWidth > 0 && drawHeight > 0) {
image(drawObject.img, x, 400-(drawHeight/2),drawWidth, drawHeight);
//calculates font size relative to object's current size
int textSize;
//checks if the name or diameter is longer, then uses the longer one for calculation
fill(255,255,255);
if (drawObject.name.length() < str(drawObject.diameter).length()) {
textSize = int(drawWidth/str(drawObject.diameter).length());
} else {
textSize = int(drawWidth/drawObject.name.length());
}
if (textSize > 0) {
textSize(textSize);
float texty = 418+(drawHeight/2);
if (texty < (418+(drawHeight/2))) {
texty = 418;
}
text(drawObject.name, x+(drawWidth/2), texty);
text(drawObject.diameter+drawObject.unit, x+(drawWidth/2), texty+textSize);
}
}
}
drawObject.xpos = x;
x += (drawWidth*0.08 + drawWidth);
//display deltax
textSize(32);
text(str(deltax), 1450, 10);
text(str(deltascale), 1450, 50);
//display Saved
//if (savetimer > 0) {
// text("Saved", 1450, 90);
// //text(str(savetimer),1450,130);
//}
//if (savetimer > 0) {
// //savetimer -= 1;
//}
println(str(scale));
}
}
void mouseWheel(MouseEvent event) {
float e = event.getCount();
if (e < 0) {
scale *= (1 + deltascale);
} else if (e > 0) {
scale *= (1 - deltascale) ;
}
}
void keyPressed() {
if (key == CODED) {
if (keyCode == LEFT) {
xoffset += deltax;
} else if (keyCode == RIGHT) {
xoffset -= deltax;
} else if (keyCode == UP) {
deltax += 5;
} else if (keyCode == DOWN) {
deltax -= 5;
}
}
if (key == 'r') {
//reloadObjects();
} else if (key == 'q') {
deltascale += 0.02;
} else if (key == 'a') {
deltascale -= 0.02;
}
if (deltax < 0) {
deltax = 0;
} else if (deltascale < 0) {
deltascale = 0;
}
}
void keyReleased() {
//reloadObjects();
}
void reloadObjects() {
for ( Object reloadObject : ObjectList ) {
float dia = reloadObject.diameter;
//int drawWidthh = int(scale * dia);
if (reloadObject.xpos > 0 && reloadObject.xpos+reloadObject.img.width <= 1500) {
reloadObject.img = loadImage(reloadObject.sprite);
}
}
}
使用鼠标滚轮放大和缩小以及左右箭头键进行导航。谢谢!
答案 0 :(得分:0)
您可以使用pushMatrix()
/ popMatrix()
来调用一堆嵌套转换来跟踪坐标空间。
您可以按照2D Transformations Processing Tutorial了解详情。
这是一个快速评论的草图,解释了这个概念:
//a position to scale from
PVector mouse = new PVector();
//a scale value
float scale = 1.0;
//drawing dimensions - this depends on your actual content
float w = 400;
float h = 400;
void setup(){
size(400,400);
rectMode(CENTER);
}
void draw(){
background(255);
//move everything to centre
translate(width * .5, height * .5);
//isolate coordinate space
pushMatrix();
//move in the opposite direction by half of the drawing size => transform from drawing centre
translate(-w * .5,-h * .5);
//move to where the transformation centre should be (this can be mixed with the above, but I left it on two lines so it's easier to understand)
translate(mouse.x,mouse.y);
//transform from set position
scale(scale);
//move the transformation back
translate(-mouse.x,-mouse.y);
//draw what you need to draw
drawStuff();
//return to global coordinate space
popMatrix();
//draw a preview of the transformation centre
if(mousePressed){
fill(192,0,0);
ellipse(mouse.x-width*.5,mouse.y-height*.5,35,35);
}
}
//just a bunch of boxes as a placeholder
void drawStuff(){
for(int i = 0 ; i < 400; i++){
int x = i % 20;
int y = i / 20;
pushMatrix();
translate(x * 20, y * 20);
rotate(radians(i));
scale(sin(radians(i)) + 1.1);
fill(i % 400);
rect(0,0,15,15);
popMatrix();
}
}
//set the transformation centre
void mousePressed(){
mouse.set(mouseX,mouseY);
}
//change scale by moving mouse on X axis
void mouseDragged(){
scale = map(mouseX,0,width,0.25,2.0);
}
您可以运行以下演示:
//a position to scale from
var mouse;
//a scale value
var scl = 1.0;
//drawing dimensions - this depends on your actual content
var w = 400;
var h = 400;
function setup(){
mouse = createVector(0,0);
createCanvas(400,400);
rectMode(CENTER);
}
function draw(){
background(255);
//move everything to centre
translate(width * .5, height * .5);
//isolate coordinate space
push();
//move in the opposite direction by half of the drawing size => transform from drawing centre
translate(-w * .5,-h * .5);
//move to where the transformation centre should be (this can be mixed with the above, but I left it on two lines so it's easier to understand)
translate(mouse.x,mouse.y);
//transform from set position
scale(scl);
//move the transformation back
translate(-mouse.x,-mouse.y);
//draw what you need to draw
drawStuff();
//return to global coordinate space
pop();
//draw a preview of the transformation centre
if(mousePressed){
fill(192,0,0);
ellipse(mouse.x-width*.5,mouse.y-height*.5,35,35);
}
}
//just a bunch of boxes as a placeholder
function drawStuff(){
for(var i = 0 ; i < 400; i++){
var x = i % 20;
var y = i / 20;
push();
translate(x * 20, y * 20);
rotate(radians(i));
scale(sin(radians(i)) + 1.1);
fill(i % 400);
rect(0,0,15,15);
pop();
}
}
//set the transformation centre
function mousePressed(){
mouse.set(mouseX,mouseY);
}
//change scale by moving mouse on X axis
function mouseDragged(){
scl = map(mouseX,0,width,0.25,2.0);
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.8/p5.js"></script>
&#13;